Repository navigation
feat: articles on string types and object type inferences - #31
JoshuaKGoldberg wants to merge 4 commits into
Conversation
| Why does TypeScript report a `string` type instead of `keyof typeof` the object when you use a `for...in` loop or `Object.keys()` on an object? | ||
|
|
||
| One of the most commonly asked questions in TypeScript help forums is why code like the following gives an error under the [`noImplicitAny` compiler option](https://www.typescriptlang.org/tsconfig#noImplicitAny). |
There was a problem hiding this comment.
[Nitpick/proofreading] Hmmm..., there seems to be some ambiguity in this part of your article. Maybe you can try the suggestion below to make it clearer.
| Why does TypeScript report a `string` type instead of `keyof typeof` the object when you use a `for...in` loop or `Object.keys()` on an object? | |
| One of the most commonly asked questions in TypeScript help forums is why code like the following gives an error under the [`noImplicitAny` compiler option](https://www.typescriptlang.org/tsconfig#noImplicitAny). | |
| One of the most commonly asked questions in TypeScript help forums is why code like the one below gives an error under the [`noImplicitAny` compiler option](https://www.typescriptlang.org/tsconfig#noImplicitAny). |
| TypeScript's type system is _structurally typed_: meaning any value that happens to satisfy a type is allowed to be used as a value of that type. | ||
| In other words, when you declare that a value is of a particular object type, you're telling TypeScript any object that just so happens to have those properties is allowed to be considered that type. | ||
|
|
||
| As a result, when you write a `for...in` loop over the keys of an object, you often won't have a guarantee that the object's keys will only be from the type of the object. |
There was a problem hiding this comment.
[nitpick/proofreading] This paragraph could be a bit clearer. The first introductory phrase (As a result) creates a repetitive flow because the other phrase "when you write" conveys the same idea.
| As a result, when you write a `for...in` loop over the keys of an object, you often won't have a guarantee that the object's keys will only be from the type of the object. | |
| As a result, writing a `for...in` loop over the keys of an object won't often guarantee that the object's keys will only be from the type of the object. |
| In other words, when you declare that a value is of a particular object type, you're telling TypeScript any object that just so happens to have those properties is allowed to be considered that type. | ||
|
|
||
| As a result, when you write a `for...in` loop over the keys of an object, you often won't have a guarantee that the object's keys will only be from the type of the object. | ||
| Some other area of code might have provided an object with more properties that just so happens to match the structural type. |
There was a problem hiding this comment.
[Proofreading] Since this sentence is describing other parts of the code, consider turning "area" into a plural noun to convey this idea clearly.
| Some other area of code might have provided an object with more properties that just so happens to match the structural type. | |
| Some other areas of code might have provided an object with more properties that just so happens to match the structural type. |
| Needing to wrestle with the type checker is often a byproduct of application code going against safe JavaScript practices -- such as the aforementioned issues with `for...in` loops receiving unexpected key strings. | ||
| In many cases, it might be good to listen to TypeScript and consider refactoring your code to use a JavaScript API better suited to the task. | ||
|
|
||
| If all your code needs to do is get all the values in an object, an `Object.values()` API exists that returns those as an array. |
There was a problem hiding this comment.
[Proofreading/nitpick/question] I edited the sentence a bit to make it clearer. Is the below suggestion the message you want to convey?
| If all your code needs to do is get all the values in an object, an `Object.values()` API exists that returns those as an array. | |
| If all your code needs all an object's values, an `Object.values()` API exists to return those as an array. |
| Taking an even larger step back, why is the application code looping over an object's keys and values? | ||
| Is the object meant to be used as a general key-value store? | ||
|
|
||
| If so: consider using the built-in `Map` data structure instead. |
There was a problem hiding this comment.
[Proofreading/typo] It's always best to use a comma for introductory elements.
| If so: consider using the built-in `Map` data structure instead. | |
| If so, consider using the built-in `Map` data structure instead. |
| ### Type Assertions | ||
|
|
||
| Still, there are times when a `for...in` loop or `Object.keys()` might likely be mostly safe to use for object keys. | ||
| If you are 100% absolutely completely sure that your use case won't crash from some bizarre type mismatch now or in the future, you can always use an `as` assertion to cast the loop variable to the right type. |
There was a problem hiding this comment.
[Proofreading/nitpick] While mentioning "completely" and "absolutely" encourages devs to think deeply about the use case, I think saying "100% sure" conveys this point perfectly.
| If you are 100% absolutely completely sure that your use case won't crash from some bizarre type mismatch now or in the future, you can always use an `as` assertion to cast the loop variable to the right type. | |
| If you are 100% sure that your use case won't crash from some bizarre type mismatch now or in the future, you can always use an `as` assertion to cast the loop variable to the right type. |
| TypeScript's type system boasts a feature called _type narrowing_. | ||
| Type narrowing means that if a block of code can only be reached when a value is a specific type, then the value will be considered that type inside the block. | ||
|
|
||
| As an example, take the following `fruit` variable of type `string | undefined` (a union type indicating it can be either `string` or `undefined`. |
There was a problem hiding this comment.
[Proofreading] Hmmm...I think using "for" instead of "as a" would make the sentence clearer.
| As an example, take the following `fruit` variable of type `string | undefined` (a union type indicating it can be either `string` or `undefined`. | |
| For example, take the following `fruit` variable of type `string | undefined` (a union type indicating it can be either `string` or `undefined`. |
| ### A Practical Example | ||
|
|
||
| Let's say you want to `console.log` the `counts` object before reassigning a new value to a count. | ||
| Your use your own custom `log` function that just so happens to only call `console.log`? |
There was a problem hiding this comment.
[Nitpicking/proofreading/question] This part seems more like statement. Did you mean to make it a question?
| Your use your own custom `log` function that just so happens to only call `console.log`? | |
| But your use your own custom `log` function that just so happens to only call `console.log`. |
| TypeScript's type system boasts a feature called _type narrowing_. | ||
| Type narrowing means that if a block of code can only be reached when a value is a specific type, then the value will be considered that type inside the block. | ||
|
|
||
| As an example, take the following `fruit` variable of type `string | undefined` (a union type indicating it can be either `string` or `undefined`. |
There was a problem hiding this comment.
[Proofreading] Seems similar to this part in the other article.
| As an example, take the following `fruit` variable of type `string | undefined` (a union type indicating it can be either `string` or `undefined`. | |
| For example, take the following `fruit` variable of type `string | undefined` (a union type indicating it can be either `string` or `undefined`. |
CBID2
left a comment
There was a problem hiding this comment.
Hi @JoshuaKGoldberg! :) I added some in-line comments on how you can improve your articles grammar-wise. Other than that, You're are off to a great start! Good job! 😄 👍🏾
|
@CBID2 thanks for looking at this. It's a very old draft I'm not likely to pick up any time soon though. I wouldn't recommend giving reviews on any old blog drafts of mine. Some of them last for months or years before I close or drastically rewrite 😄 |
Ah ok @JoshuaKGoldberg. Well, if you ever change your mind, they're there lol 😂 |
Overview
Sending these two in a single PR for now as one references the other. Will likely split out.