-
Notifications
You must be signed in to change notification settings - Fork 0
Chapter 7 #7
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
base: initial
Are you sure you want to change the base?
Conversation
|
||
#### How TypeScript Infers `const` | ||
|
||
When using `const`, the variable is _immutable_ and cannot be reassigned. When we change the variable declaration to use `const`, TypeScript will infer the type more narrowly: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i wouldnt be surprised if somebody would take away from this that objects declared using const
are immutable too but that's not true. I'd adjust the lingo used here to avoid mentioning immutability.
albumAttributes.status = "new-release"; | ||
``` | ||
|
||
This is true even though the `albumAttributes` object was declared with `const`. We get the error when calling `updateStatus` because `status: string` can't be passed to a function that expects `status: "new-release" | "on-sale" | "staff-pick"`. TypeScript is trying to protect us from potential runtime errors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is true even though the
albumAttributes
object was declared withconst
I feel like this should be explained explicitly here - less experienced readers might get lost here as it seemingly contradicts some of the things said earlier. I know that this section also mentions smth like:
Objects are mutable in JavaScript, meaning their properties can be changed after they are created.
but I still feel like it might be a little bit hard to connect the dots here
|
||
### Readonly Arrays | ||
|
||
As with object properties, arrays and tuples can also be made immutable by using the `readonly` modifier. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i never thought about it before but it's interesting that readonly
modifier for arrays/tuples is applied on the whole thing - making all elements readonly - while in objects we can apply that only on property level
printGenresMutable(readOnlyGenres); | ||
``` | ||
|
||
This is because we might be mutating the array inside of `printGenresMutable`. If we passed a read-only array. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's technically not exactly true. It's not because the function could mutate the array inside. If that were true then this would be illegal too:
type ReadonlyObj = { readonly foo: string }
function changeObj(obj: { foo: string }) {
obj.foo = 'bazinga'
}
const obj: ReadonlyObj = { foo: 'bar' }
changeObj(obj) // it would be an error if the above statement would be true
The reason why it's illegal to pass a readonly array to a spot expecting a mutable array is purely structural. Just like you mentioned, the readonly ones don't have push
, pop
and maybe some other things too. So it's as if you'd try to do this:
function require2Props(obj: { a: number, b: string }) {}
require2Props({ a: 42 }) // error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But also... we might actually get a new tsconfig option that will help people to benefit from a stricter set of rules: microsoft/TypeScript#58296
}; | ||
``` | ||
|
||
The `as const` assertion has made the entire object deeply read-only, including all of its properties. This means that `albumAttributes.status` is now inferred as the literal type `"on-sale"`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be worth noting here that it will only work for "fresh" parts of as const
ed object: TS playground
|
||
We can also see that when `undefined` is placed into an array with `any`, TypeScript infers the array as `any[]`. This is TypeScript's second mistake - collapsing our `undefined` value so it all but disappears. | ||
|
||
However, by using `as const`, TypeScript correctly infers the return value as a tuple (`Promise<[string | undefined, any]>`). This is a great example of how `as const` can help TypeScript give us the best type inference possible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, by using `as const`, TypeScript correctly infers the return value as a tuple (`Promise<[string | undefined, any]>`). This is a great example of how `as const` can help TypeScript give us the best type inference possible. | |
However, by using `as const`, TypeScript correctly infers the return value as a tuple (`Promise<readonly [Error] | readonly [undefined, any]>`). This is a great example of how `as const` can help TypeScript give us the best type inference possible. |
|
||
But again, this is still typed strongly enough to to satisfy `modifyButtons`. | ||
|
||
When using `as const` like this acts like a hint to TypeScript that it should infer a literal type where it wouldn't otherwise. This can be occasionally useful for when you want to allow mutation, but still want to infer a literal type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A neat trick is to also know how to infer a tuple using as const
without making the tuple itself readonly. That can be done using as const satisfies unknown[]
but you haven't introduced satisfies
yet... so probably not worth mentioning it here
No description provided.