-
Notifications
You must be signed in to change notification settings - Fork 0
Chapter 9 #9
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
|
||
Compared to handling the assignment manually, this saves a lot of code and keeps the class definition concise. | ||
|
||
But unlike other TypeScript features, the outputted JavaScript is not a direct representation of the TypeScript code. This can make it difficult to understand what's happening if you're not familiar with the feature. |
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 can also introduce (at least at the moment) some unexpected issues in your code. You have mentioned before that class properties are initialized before the constructor gets executed. This is a fair approximation. So what about those properties? We could say the same about them - they are initialized at the beginning of the constructor. So which one runs first? Well, take a look at this:
// input
class Foo {
prop = "foo";
constructor(public foo: string = this.prop) {}
}
// output
"use strict";
class Foo {
constructor(foo = this.prop) {
this.foo = foo;
this.prop = "foo";
}
}
Oops, not cool 😉
|
||
But the fact that they're not consistent with numeric enums can be a source of confusion. | ||
|
||
In fact, string enums are unique in TypeScript because they're compared _nominally_. All other types in TypeScript are compared _structurally_, meaning that two types are considered the same if they have the same structure. But string enums are compared based on their name (nominally), not their structure. |
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.
In fact, string enums are unique in TypeScript because they're compared _nominally_. All other types in TypeScript are compared _structurally_, meaning that two types are considered the same if they have the same structure. But string enums are compared based on their name (nominally), not their structure. | |
In fact, string enums are unique in TypeScript because they're compared _nominally_. Most other types in TypeScript are compared _structurally_, meaning that two types are considered the same if they have the same structure. But string enums are compared based on their name (nominally), not their structure. |
logStatus(AlbumStatus2.NewRelease); | ||
``` | ||
|
||
For those of us used to structural typing, this can be a bit of a surprise. But to developers used to enums in other languages, string enums will feel the most natural. |
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.
The callout is good but it feels like the first time structural typing and nominal typing were called out here so I wouldn't be surprised if the reader just wouldn't know what you are talking about in this section
let albumStatuses = ["NEW_RELEASE", "ON_SALE", "STAFF_PICK"]; | ||
``` | ||
|
||
`const` enums do have some limitations, especially when declared in declaration files (which we'll cover later). The TypeScript team actually recommends avoiding `const` enums in your library code because they can behave unpredictably for consumers of your library. |
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 calling out that one of the major limitations is that only TS can emit code using them, some other tools might have partial support too (IIRC esbuild
handles them - at least to some extent, I'm not sure) but they are not guaranteed to work if using other tools. But maybe that goes outside of the scope of this book, dunno
logStatus(3); | ||
``` | ||
|
||
This is different from string enums, which only allow the enum members to be used as types: |
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 nice to call out that the reverse can be done:
enum MyEnum {
foo = 'FOO',
bar = 'BAR'
}
const test1: MyEnum.foo = 'FOO' // error
const test2: "FOO" = MyEnum.foo // ok
String enums are kind of subtypes of their string literal counterparts.
} | ||
} | ||
|
||
const madvillainy: RecordStoreUtils.Album = { |
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 respect this example
``` | ||
|
||
This information will become crucial later when we look at the namespace's key use case: globally scoped types. | ||
|
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 guess you could document this pattern too:
function test(opts: test.Options) {
opts.foo;
}
namespace test {
export type Options = {
foo: string;
};
}
what is nice about it that there is no added runtime to this, it's just a function with some types collocated to it
|
||
The way string enums behave feels more natural - it matches how enums work in other languages like C# and Java. | ||
|
||
But the fact that they're not consistent with numeric enums can be a source of confusion. |
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 also came to my attention recently that numeric enums are just not type-safe... to support usage of bitmasks
No description provided.