Skip to content

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

Open
wants to merge 1 commit into
base: initial
Choose a base branch
from
Open

Chapter 7 #7

wants to merge 1 commit into from

Conversation

Andarist
Copy link
Owner

No description provided.


#### 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:
Copy link
Owner Author

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.
Copy link
Owner Author

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 with const

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.
Copy link
Owner Author

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.
Copy link
Owner Author

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

Copy link
Owner Author

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"`.
Copy link
Owner Author

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 consted 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.
Copy link
Owner Author

Choose a reason for hiding this comment

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

Suggested change
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.
Copy link
Owner Author

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

@Andarist Andarist marked this pull request as ready for review July 14, 2024 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy