GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — Static types for dynamically named properties by ahejlsberg · Pull Request #11929 · microsoft/TypeScript Conversation
|
|
Anders Hejlsberg (@ahejlsberg) Does this also adjust the logic for handling actual index expressions? For example, interface Foo { a: 0 b: 1 } var x: "a" | "b"; var y: Foo; var z = y[x]; // Is this Foo["a" | "b"] or 0 | 1 (rather than relying on a nonexistant index signature for the type or being any)? Or is actual indexing unchanged? IMO, it would make the most sense if the typespace indexing operator and the valuespace one affected type flow in the same way. This was the last half-feature/concern I had identified in the original issue. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
Wesley Wigham (@weswigham) The operation EDIT: The remaining unification is done and BTW, there is an interesting issue around reading vs. writing when the index type is not a unit type. Technically, it is only safe to union together the resulting values when you're reading. For writing, the only safe construct would be an intersection, but that is rarely useful. So, we're planning to make writing an error when the index type is not a unit type: interface Foo { a: 0, b: 1 } function f1(foo: Foo, x: "a" | "b") { const c = foo[x]; // Ok, type 0 | 1 foo[x] = c; // Error, absent index signatures an index expresion must be of a unit type } However, in the parametric case we make no distinction between function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]) { obj[key] = value; } function f2(foo: Foo, x: "a" | "b") { const c = foo[x]; // Ok, type 0 | 1 setProperty(foo, x, c); // Ok } It actually seems fairly reasonable to allow this. Really, there are three distinct possibilities:
The alternative is to have distinct safe for reading, safe for writing, and safe for reading and writing versions of |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
Latest set of commits unify type checking of indexed access expressions and indexed access types. Also, improved error messages for a number of errors related to property/element access and constant/read-only checking. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
# Conflicts: # src/compiler/diagnosticMessages.json
| /* @internal */ | ||
| resolvedIndexType: IndexType; | ||
| /* @internal */ | ||
| resolvedIndexedAccessTypes: IndexedAccessType[]; |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
why array instead of map? the array is going to be sparse if indexed with type id.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Yes, it will be sparse, in the same way that our nodeLinks and symbolLinks arrays are sparse. I believe this performs better than a map.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| return indexedAccessTypes[objectType.id] || (indexedAccessTypes[objectType.id] = createIndexedAccessType(objectType, indexType)); | ||
| } | ||
|
|
||
| function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode) { |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
should not this be getPropertyTypeForIndexedType or getPropertyTypeForIndexAccess since it operates on the indexed type rather than the index type.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Well, it operates both on the indexed type and the index type. So, technically it should be getPropertyTypeForIndexedTypeIndexedByIndexType. 😃 Honestly, not sure what would be a good name.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| "code": 7016 | ||
| }, | ||
| "Index signature of object type implicitly has an 'any' type.": { | ||
| "Element implicitly has an 'any' type because type '{0}' has no index signature.": { |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
🎉 this is much better now!
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, (<LiteralType>indexType).text, typeToString(objectType)); | ||
| } | ||
| else if (indexType.flags & (TypeFlags.String | TypeFlags.Number)) { | ||
| error(accessNode, Diagnostics.Type_0_has_no_matching_index_signature_for_type_1, typeToString(objectType), typeToString(indexType)); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
i do not see any tests for this scenario.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Right, I still haven't added tests.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I do not see any tests for keyof and/or T[K]. also please include some declaration emit tests.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I wonder whether index access type works with constrained generic parameter. For example, only the last alias of the following three is resolved to type A<T extends {[K in "test"]: any}> = T["test"] type B<T extends {test: any}> = T["test"] type C<T extends {test: any}, K extends keyof T> = T[K] type A1 = A<{test: number}> type B1 = B<{test: number}> type C1 = C<{test: number}, "test"> Is this intended? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Herrington Darkholme (@HerringtonDarkholme) In an indexed access |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Anders Hejlsberg (@ahejlsberg) what about support for regex check type? like this: |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Is there no way to make private members accessible? Would be nice if you could do something similar to the readonly transformation. My Specific example is when transforming the current class to the IOnChangesObject in angular. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
type Foo<T> = T & { Test: () => void; } type Foo1<T> = keyof Foo<T>; type Foo2 = Foo1<{ prop: string }>; type Foo2 = "Test" |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Should this also work for object literals? I would have expected the following to also work: const thing = { a: 'foo', b: 'bar', }; // Expected: "a" | "b" // Actual: Cannot find name 'thing' type thingKey = keyof thing; |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
Ian MacLeod (@nevir) Use type thingKey = keyof typeof thing; |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Ah! Thanks! |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
just want to share it here: ////////////////////////////////// USAGE ///////////////////////////////// var sequelize = new Sequelize(); var Users = sequelize.define("users", { firstName: STRING, lastName: CHAR(123), age: INTEGER, visits: { type: INTEGER, length: 4} }); var u = Users.create({age: 22}); // only valid fields/types allowed u.firstName = "John"; // types are checked at compile time u.lastName = "Doe" u.visits = 123; ///////////////////////////////// DECLARATIONS ///////////////////////////// interface ABSTRACT_STATIC<T> { prototype: ABSTRACT<string, T>; } interface ABSTRACT_BASE<T> { stringify(value: T, options): string; validate(value: T); } interface ABSTRACT<Key, T> extends ABSTRACT_BASE<T> { key: Key; dialectTypes: string; toSql: string; warn(link: string, text); } interface STRING_OPTIONS { length?: number, binary?: boolean } interface STRING<Key> extends ABSTRACT<Key, string> { readonly BINARY: this } interface STRING_STATIC<Key, T extends STRING<Key>> extends ABSTRACT_STATIC<string> { new(length?: number, binary?: boolean): T; new(options: STRING_OPTIONS): T; (length?: number, binary?: boolean): T; (options: STRING_OPTIONS): T; } declare const STRING: STRING_STATIC<"STRING", STRING<"STRING">>; interface CHAR extends STRING<"CHAR"> {} interface CHAR_STATIC extends STRING_STATIC<"CHAR", CHAR> {} declare const CHAR: CHAR_STATIC; interface NUMBER_OPTIONS { length?: number, zerofill?: boolean, decimals?: number, precision?: number, scale?: number, unsigned?: boolean } interface NUMBER<Key> extends ABSTRACT<Key, number> { readonly UNSIGNED: this readonly ZEROFILL: this } interface NUMBER_STATIC<Key, T extends NUMBER<Key>> extends ABSTRACT_STATIC<number> { new(options: NUMBER_OPTIONS): T; (options: NUMBER_OPTIONS): T; } declare const NUMBER: NUMBER_STATIC<"NUMBER", NUMBER<"NUMBER">>; interface INTEGER extends NUMBER<"INTEGER"> {} interface INTEGER_STATIC extends NUMBER_STATIC<"INTEGER", INTEGER> { new(): INTEGER; (): INTEGER; new(length: number): INTEGER; (length: number): INTEGER; } declare const INTEGER: INTEGER_STATIC; interface OPTIONS<T> { type: ABSTRACT_STATIC<T> } interface STRING_OPTIONS_TYPE extends OPTIONS<string>, STRING_OPTIONS { } interface NUMBER_OPTIONS_TYPE extends OPTIONS<number>, NUMBER_OPTIONS { } type FIELD<T> = ABSTRACT_STATIC<T> | OPTIONS<T> & ( STRING_OPTIONS_TYPE | NUMBER_OPTIONS_TYPE ) | ABSTRACT_BASE<T> type INIT<T> = {[P in keyof T]?:T[P]} declare class Factory<T> { create(initial?: INIT<T>): T } declare class Sequelize { define<T>(tableName: string, fields: {[P in keyof T]: FIELD<T[P]>}):Factory<T> } |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.