Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(blocks): Migrate blocks/text.js to TypeScript #6958

Merged
merged 8 commits into from
Apr 28, 2023

Conversation

rachel-fenichel
Copy link
Collaborator

@rachel-fenichel rachel-fenichel commented Apr 7, 2023

The basics

  • I branched from develop
  • My pull request is against develop
  • My code follows the style guide
  • I ran npm run format and npm run lint

The details

Resolves

Part of #6828

Proposed Changes

Behavior Before Change

Behavior After Change

Reason for Changes

Test Coverage

Documentation

Additional Information

@rachel-fenichel
Copy link
Collaborator Author

@cpcallen fyi I made a start on the text blocks, but will need type help to disentangle some of the combinations of extensions and mixins.

blocks/text.ts Outdated
@@ -339,15 +334,15 @@ blocks['text_getSubstring'] = {
const menu = fieldRegistry.fromJson({
type: 'field_dropdown',
options: this['WHERE_OPTIONS_' + n],
Copy link
Collaborator Author

@rachel-fenichel rachel-fenichel Apr 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cpcallen What do you think I should do for this dynamic access to WHERE_OPTIONS_1 and WHERE_OPTIONS_2?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First I would try typing the parameter n: 1|2, which should probably be the case in any case.

If that doesn't fix a type error here then I'd try this just in case it helps:

Suggested change
options: this['WHERE_OPTIONS_' + n],
options: this['WHERE_OPTIONS_' + (n as 1|2)],

but probably it wouldn't, so then it might be necessary to resort to :

Suggested change
options: this['WHERE_OPTIONS_' + n],
options: this[('WHERE_OPTIONS_' + n) as 'WHERE_OPTIONS_1'|'WHERE_OPTIONS_2'],

…and if that doesn't work then maybe ultimately it might be necessary to do something like:

Suggested change
options: this['WHERE_OPTIONS_' + n],
options: n === 1 ? this.WHERE_OPTIONS_1 : this.WHERE_OPTIONS_2;

(but I'd really rather we didn't!)

blocks/text.ts Outdated
@@ -282,7 +279,7 @@ blocks['text_getSubstring'] = {
* @return {!Element} XML storage element.
* @this {Block}
*/
mutationToDom: function() {
mutationToDom: function(this: Block): Element {
const container = xmlUtils.createElement('mutation');
const isAt1 = this.getInput('AT1').type === ConnectionType.INPUT_VALUE;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cpcallen this.getInput('AT') is possible null, because it's added and removed dynamically. Is there a way to guarantee that it's present, or should I just use ! to assert that it is non-null?

Copy link
Contributor

@cpcallen cpcallen Apr 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for now just use ! (since we presume the existing code is not broken), but then in the next pass we actually add checks for these things (via ?. where convenient and more explicitly via if (bad) throw new SomeError() where necessary).

@cpcallen cpcallen changed the title Convert text refactor(blocks): Migrate `blocks/text.js to TypeScript Apr 21, 2023
@cpcallen cpcallen changed the title refactor(blocks): Migrate `blocks/text.js to TypeScript refactor(blocks): Migrate blocks/text.js to TypeScript Apr 21, 2023
@rachel-fenichel rachel-fenichel marked this pull request as ready for review April 22, 2023 00:21
@rachel-fenichel rachel-fenichel requested a review from a team as a code owner April 22, 2023 00:21
@rachel-fenichel
Copy link
Collaborator Author

@cpcallen this is ready for review!

@BeksOmega BeksOmega assigned cpcallen and unassigned BeksOmega Apr 24, 2023
@BeksOmega BeksOmega removed their request for review April 24, 2023 14:54
Copy link
Contributor

@cpcallen cpcallen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cpcallen this is ready for review!

Don't forget to update the PR description.

const isAt2 = this.getInput('AT2').type === ConnectionType.INPUT_VALUE;
container.setAttribute('at2', isAt2);
const isAt1 = this.getInput('AT1')!.type === ConnectionType.INPUT_VALUE;
container.setAttribute('at1', `${isAt1}`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: I had a look recently to see if String(x) or `${x}` to typecast the second parameter of setAttribute calls. We use both, with String being slightly more popular.

blocks/text.ts Show resolved Hide resolved
blocks/text.ts Outdated Show resolved Hide resolved
blocks/text.ts Outdated Show resolved Hide resolved
blocks/text.ts Show resolved Hide resolved
*/
compose: function(containerBlock) {
let itemBlock = containerBlock.getInputTargetBlock('STACK');
compose: function(this: JoinMutatorBlock, containerBlock: Block) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

containerBlock could be a more specific type, if you define one.

blocks/text.ts Outdated
compose: function(containerBlock) {
let itemBlock = containerBlock.getInputTargetBlock('STACK');
compose: function(this: JoinMutatorBlock, containerBlock: Block) {
let itemBlock = containerBlock.getInputTargetBlock('STACK') as BlockSvg;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to say as JoinMutatorItemBlock here, to avoid the cast below.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I do that, I have to cast every time I call getNextBlock, because it returns BlockSvg and that may not have a valueConnection_ on it.

I could declare it so that getNextBlock overrides and returns a JoinItemBlock but I don't think that's better than treating it as a BlockSvg overall and a JoinItemBlock when I need the valueConnection_.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Attempt #N at writing a coherent reply comment here:)

I think casting the result of getNextBlock() is the correct thing to do in any case (at least pending adding an actual runtime type check in a future PR), but I don't think it matters very much for overall.

blocks/text.ts Outdated Show resolved Hide resolved
*/
saveConnections: function(containerBlock) {
saveConnections: function(this: JoinMutatorBlock, containerBlock: Block) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again: a more specific type for containerBlock should be possible and might be useful.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm neutral on the specific type for the container block. Do you want me to add it? My default is to leave it alone.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's not useful at the moment then I agree about leaving it alone.

blocks/text.ts Outdated
*/
const TEXT_INDEXOF_TOOLTIP_EXTENSION = function() {
const INDEXOF_TOOLTIP_EXTENSION = function(this: Block) {
// Assign 'this' to a variable for use in the tooltip closure below.
const thisBlock = this;
this.setTooltip(function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not done in previous blocks PRs, but noting the impending PR #7014 enables eslint in theblocks/ directory: might as well use an arrow function here, and avoid the wrath of eslint (and the need for const thisBlock = this).

Copy link
Contributor

@cpcallen cpcallen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With one nit (remove Mixin from a Block type's name) this LGTM.

blocks/text.ts Outdated
Comment on lines 654 to 657
/** Type of a block that has QUOTE_IMAGE_MIXIN */
type QuoteImageMixinBlock = Block&QuoteImageMixin;
interface QuoteImageMixin extends QuoteImageMixinType {}
type QuoteImageMixinType = typeof QUOTE_IMAGE_MIXIN;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, but can we at least remove "Mixin" from QuoteImageMixinBlock? Because otherwise (for consistency with the naming convention established everywhere else) the other two should be QuoteImageMixinMixin and QuiteImageMixinMixinType.

blocks/text.ts Outdated
compose: function(containerBlock) {
let itemBlock = containerBlock.getInputTargetBlock('STACK');
compose: function(this: JoinMutatorBlock, containerBlock: Block) {
let itemBlock = containerBlock.getInputTargetBlock('STACK') as BlockSvg;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Attempt #N at writing a coherent reply comment here:)

I think casting the result of getNextBlock() is the correct thing to do in any case (at least pending adding an actual runtime type check in a future PR), but I don't think it matters very much for overall.

@rachel-fenichel rachel-fenichel merged commit d47369a into google:develop Apr 28, 2023
@rachel-fenichel rachel-fenichel deleted the convert_text branch April 28, 2023 17:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants