| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
# Conflicts: # src/compiler/checker.ts # src/server/utilities.ts
|
Luke Garrison (@lkgarrison), that package has not yet been updated to use unique symbol, though a PR will be posted shortly. |
Sorry, something went wrong.
|
Any recommendations for how library developers should proceed with this breaking change? For example, I maintain a project available via npm, written in typescript, and distribute its type definitions file (which includes generic types and method signatures involving keyof T) with the npm package. It currently depends on keyof only returning string types, and, up til now, was compatible with all TypeScript versions since 2.3. I could modify the source code to compile in TypeScript 2.9 by replacing all instances of keyof T with Extract<keyof T, string>, but then the type definitions file that I generate/distribute will cause compiler errors for anyone attempting to use my npm package with TypeScript versions 2.3-2.7 (because Extract is new for 2.8). Are there any tricks I can use to define my generic classes/methods involving keyof T so that they are valid for for both version 2.9 and pre-2.9, without requiring all users of my package to use the --keyofStringsOnly compiler option? Is there some way to conditionally define a generic type differently depending on TypeScript versions. I basically need (example inspired by C compiler directives): #if TYPESCRIPT_VERSION >= 2.9
type ExtractStringKeysType<T> = Extract<keyof T, string>;
#else
type ExtractStringKeysType<T> = keyof T;
#endif |
Sorry, something went wrong.
|
keyof T & string is a generally backcompat way to mostly accomplish the same thing as the extract type. |
Sorry, something went wrong.
|
Jeff Lau (@UselessPickles) I recommend using keyof any as the constraint for type parameters that represent property names (i.e. change from T extends string to T extends keyof any). keyof any resolves to string in previous versions and string | number | symbol in 2.9 so it is effectively a conditional compilation construct. |
Sorry, something went wrong.
|
Wesley Wigham (@weswigham) Thanks, I'll give that a try and report back to confirm that it works (at least for TS versions 2.3-2.9). If this is the solution, I think it should be added as a suggestion to the breaking changes documentation. Anders Hejlsberg (@ahejlsberg) That is a very useful tip (maybe should be added to the breaking changes documentation?), but actually seems to be opposite of what I was looking for (a way to consistently get only the string-like key types of some type T in all TS versions). Some more context... The project I'm trying to future-proof for TS 2.9: https://github.com/UselessPickles/ts-enum-util At the core of the problem is that I use this type as a constraint to support any "enum-like" types (objects with string keys and number | string values), but in a way that allows the exact keys and exact value types to be inferred properly for string enums, etc): export type EnumLike<V extends number | string, K extends string> = {
[P in K]: V
};Then the main generic class that uses that type constraint: export class EnumWrapper<
V extends number | string = number | string,
T extends EnumLike<V, keyof T> = any
>Which allows me to have a very strictly typed utility wrapper for any enum that knows the exact type of values in the enum (V), and the exact union of string literal enum names/keys (keyof T). I think changing my constraint in EnumWrapper to T extends EnumLike<V, keyof T & string> is more appropriate than changing the constraint in EnumLike to K extends keyof any, because enums should only have string keys. |
Sorry, something went wrong.
|
Wesley Wigham (@weswigham) Unfortunately, the keyof T & string trick doesn't work for me :(. It only works in TS 2.9. Prior to TS 2.9, the & string part sticks around as part of the type, and prevents me from using it to index into type T to get the type of the properties in T. For example: interface Test {
A: number;
B: string;
}
type StringKeys<T> = keyof T & string;
type StringKeyValues<T> = T[StringKeys<T>];
// expect: "A" | "B"
// got: ("A" & string) | ("B" & string)
type Keys = StringKeys<Test>;
// expect: number | string
// got: any
type Values = StringKeyValues<Test>; |
Sorry, something went wrong.
|
I am trying to set an enum as the key of an interface in 2.7.2: so I can have objects as {'a':1} Am I doing something wrong? |
Sorry, something went wrong.
|
Marta Galve (@seaBubble) The type of the index signature key can only be number or string. You have to use a mapped type to create an interface whose keys are the values of a string enum: enum TestEnum {
A = 'a',
B = 'b'
}
type TestCounter = { [P in TestEnum]: number };
const testCounter: TestCounter = {
[TestEnum.A]: 0,
[TestEnum.B]: 0
};This can be further generalized with generics, and can also work with string literal unions. Check out my generic strictly typed string visitor/mapper utility for more advanced generic examples: https://github.com/UselessPickles/ts-string-visitor In particular, look at the StringMapperCore interface in src/StringMapper.ts. |
Sorry, something went wrong.
|
Anders Hejlsberg (@ahejlsberg) will there be support for enum E = { A, B }
declare const keyedByEnum: { [ P in E ]: any; }
for (const key in keyedByEnum) {
// key needs to be of type E
}and const keys = Object.keys(keyedByEnum); // keys need to be E[]? |
Sorry, something went wrong.
|
In both cases the key is a string. |
Sorry, something went wrong.
|
bummer, you are right
…On Sat, May 26, 2018, 21:49 Mohamed Hegazy ***@***.***> wrote:
In both cases the key is a string.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#23592 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA5PzcbfZaUivSVSVGKnjp_CXnKCbHS6ks5t2gYdgaJpZM4TeMpQ>
.
|
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
This PR adds support for number and symbol named properties in index types and mapped types. Previously, the keyof operator and mapped types only supported string named properties. Since this is technically a breaking change, the PR includes a --keyofStringsOnly compiler option that can be used to disable the new behavior in projects in which it causes errors (we expect this to be relatively rare).
Changes include:
Given an object type X, keyof X is resolved as follows:
The string-like properties of an object type are those declared using an identifier, a string literal, or a computed property name of a string literal type. The number-like properties of an object type are those declared using a numeric literal or computed property name of a numeric literal type. The symbol-like properties of an object type are those declared using a computed property name of a unique symbol type (see #15473).
In a mapped type { [P in K]: XXX }, each string literal type in K introduces a property with a string name, each numeric literal type in K introduces a property with a numeric name, and each unique symbol type in K introduces a property with a unique symbol name. Furthermore, if K includes type string, a string index signature is introduced, and if K includes type number, a numeric index signature is introduced.
Some examples:
Since keyof now reflects the presence of a numeric index signature by including type number in the key type, mapped types such as Partial<T> and Readonly<T> work correctly when applied to object types with numeric index signatures:
Furthermore, with the keyof operator's support for number and symbol named keys, it is now possible to abstract over access to properties of objects that are indexed by numeric literals (such as numeric enum types) and unique symbols.
Fixes #13715.
Fixes #14359.
Fixes #20721.
Fixes #21983.
Fixes #22105.