Skip to content
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

Allow any key type as an index signature parameter type #26797

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
cb1e630
Heavy WIP
weswigham Aug 24, 2018
b21c2ab
Merge branch 'master' into mappedtype-inference-seperate-symbols
weswigham Aug 28, 2018
8a6154a
Adjustments, fixes, and edits, oh my
weswigham Aug 28, 2018
8bdcc78
Accept most baselines
weswigham Aug 29, 2018
0183d39
A whole new paradigm of index signature relating strategies
weswigham Aug 29, 2018
4174ab9
Merge branch 'master' into mappedtype-inference-seperate-symbols
weswigham Aug 30, 2018
2c47d31
Remove grammar restriction and add tests
weswigham Aug 30, 2018
fcb90ea
Merge branch 'master' into mappedtype-inference-seperate-symbols
weswigham Sep 10, 2018
2435298
Merge branch 'master' into mappedtype-inference-seperate-symbols
weswigham Sep 26, 2018
c88702b
Merge branch 'master' into mappedtype-inference-seperate-symbols
weswigham Oct 31, 2018
d5b4d63
Merge branch 'master' into mappedtype-inference-seperate-symbols
weswigham Dec 17, 2018
28bf327
Merge branch 'master' into mappedtype-inference-seperate-symbols
weswigham Jan 26, 2019
d7c4563
Add missing instantiate call
weswigham Jan 26, 2019
dc84515
Resolve index operation on all indexers ratehr than a best indexer
weswigham Jan 28, 2019
cb0d075
Reify and check unit types in index signatures identically to mapped …
weswigham Jan 29, 2019
86e51e0
Merge branch 'master' into mappedtype-inference-seperate-symbols
weswigham Jan 29, 2019
13e614a
Merge branch 'master' into mappedtype-inference-seperate-symbols
weswigham Jan 30, 2019
96bb1af
Merge branch 'master' into mappedtype-inference-seperate-symbols
weswigham Nov 4, 2020
026ad21
Merge branch 'master' into mappedtype-inference-seperate-symbols
weswigham Dec 7, 2020
3fa71c0
Make element accesses by template literals on types with template ind…
weswigham Dec 7, 2020
ff3890f
Merge branch 'master' into mappedtype-inference-seperate-symbols
weswigham Mar 3, 2021
05f63f6
Excise well-known symbol ignoring code in index signature handling
weswigham Mar 3, 2021
4844c46
Add Anders test case, with small explaination for why it be like it i…
weswigham Mar 3, 2021
d14bd57
Merge branch 'master' into mappedtype-inference-seperate-symbols
weswigham May 17, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ namespace ts {

const binder = createBinder();

function createSymbolTable() {
return Debug.flagCheckerImmutableObject(ts.createSymbolTable());
};

export function bindSourceFile(file: SourceFile, options: CompilerOptions) {
tracing?.push(tracing.Phase.Bind, "bindSourceFile", { path: file.path }, /*separateBeginAndEnd*/ true);
performance.mark("beforeBind");
Expand Down
1,322 changes: 830 additions & 492 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,22 @@ namespace ts {
return undefined;
}

export function forEachType<T>(type: Type, f: (t: Type) => T | undefined): T | undefined {
return type.flags & TypeFlags.Union ? forEach((<UnionType>type).types, f) : f(type);
}

export function someType(type: Type, f: (t: Type) => boolean): boolean {
return type.flags & TypeFlags.Union ? some((<UnionType>type).types, f) : f(type);
}

export function everyType(type: Type, f: (t: Type) => boolean): boolean {
return type.flags & TypeFlags.Union ? every((<UnionType>type).types, f) : f(type);
}

export function everyContainedType(type: Type, f: (t: Type) => boolean): boolean {
return type.flags & TypeFlags.UnionOrIntersection ? every((type as UnionOrIntersectionType).types, f) : f(type);
}

/**
* Like `forEach`, but iterates in reverse order.
*/
Expand Down
16 changes: 16 additions & 0 deletions src/compiler/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,22 @@ namespace ts {
return value;
}

export function flagCheckerImmutableObject<T extends object>(object: T): T {
if (isDebugging) {
Object.defineProperties(object, {
__debugImmutable: {
value: true
}
});
}
return object;
}

export function assertMutable<T extends object>(object: T): T {
assert(!(object as any).__debugImmutable, "Object is flagged as checker-immutable, but is used in a position requiring mutation");
return object;
}

/**
* @deprecated Use `checkDefined` to check whether a value is defined inline. Use `assertIsDefined` to check whether
* a value is defined at the statement level.
Expand Down
24 changes: 8 additions & 16 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"category": "Error",
"code": 1022
},
"An index signature parameter type must be either 'string' or 'number'.": {
"An index signature parameter type must be assignable to 'string | number | symbol'.": {
"category": "Error",
"code": 1023
},
Expand Down Expand Up @@ -992,14 +992,6 @@
"category": "Error",
"code": 1335
},
"An index signature parameter type cannot be a type alias. Consider writing '[{0}: {1}]: {2}' instead.": {
"category": "Error",
"code": 1336
},
"An index signature parameter type cannot be a union type. Consider using a mapped object type instead.": {
"category": "Error",
"code": 1337
},
"'infer' declarations are only permitted in the 'extends' clause of a conditional type.": {
"category": "Error",
"code": 1338
Expand Down Expand Up @@ -1522,7 +1514,7 @@
"category": "Error",
"code": 2329
},
"Index signatures are incompatible.": {
"'{0}' and '{1}' index signatures are incompatible.": {
"category": "Error",
"code": 2330
},
Expand Down Expand Up @@ -1842,15 +1834,11 @@
"category": "Error",
"code": 2410
},
"Property '{0}' of type '{1}' is not assignable to string index type '{2}'.": {
"Property '{0}' of type '{1}' is not assignable to '{2}' index type '{3}'.": {
"category": "Error",
"code": 2411
},
"Property '{0}' of type '{1}' is not assignable to numeric index type '{2}'.": {
"category": "Error",
"code": 2412
},
"Numeric index type '{0}' is not assignable to string index type '{1}'.": {
"'{0}' index type '{1}' is not assignable to '{2}' index type '{3}'.": {
"category": "Error",
"code": 2413
},
Expand Down Expand Up @@ -2682,6 +2670,10 @@
"category": "Error",
"code": 2633
},
"'{0}' index signatures are incompatible.": {
"category": "Error",
"code": 2634
},

"Cannot augment module '{0}' with value exports because it resolves to a non-module entity.": {
"category": "Error",
Expand Down
13 changes: 8 additions & 5 deletions src/compiler/symbolWalker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace ts {
resolveStructuredTypeMembers: (type: ObjectType) => ResolvedType,
getTypeOfSymbol: (sym: Symbol) => Type,
getResolvedSymbol: (node: Node) => Symbol,
getIndexTypeOfStructuredType: (type: Type, kind: IndexKind) => Type | undefined,
getIndexInfosOfType: (type: Type) => readonly IndexInfo[] | undefined,
getConstraintOfTypeParameter: (typeParameter: TypeParameter) => Type | undefined,
getFirstIdentifier: (node: EntityNameOrEntityNameExpression) => Identifier,
getTypeArguments: (type: TypeReference) => readonly Type[]) {
Expand Down Expand Up @@ -140,10 +140,13 @@ namespace ts {
}

function visitObjectType(type: ObjectType): void {
const stringIndexType = getIndexTypeOfStructuredType(type, IndexKind.String);
visitType(stringIndexType);
const numberIndexType = getIndexTypeOfStructuredType(type, IndexKind.Number);
visitType(numberIndexType);
const infos = getIndexInfosOfType(type);
if (infos) {
for (const info of infos) {
visitType(info.indexType);
visitType(info.type);
}
}

// The two checks above *should* have already resolved the type (if needed), so this should be cached
const resolved = resolveStructuredTypeMembers(type);
Expand Down
21 changes: 11 additions & 10 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4056,9 +4056,9 @@ namespace ts {
getPropertyOfType(type: Type, propertyName: string): Symbol | undefined;
getPrivateIdentifierPropertyOfType(leftType: Type, name: string, location: Node): Symbol | undefined;
/* @internal */ getTypeOfPropertyOfType(type: Type, propertyName: string): Type | undefined;
getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo | undefined;
getIndexInfosOfType(type: Type, indexType?: Type): readonly IndexInfo[] | undefined;
getSignaturesOfType(type: Type, kind: SignatureKind): readonly Signature[];
getIndexTypeOfType(type: Type, kind: IndexKind): Type | undefined;
getIndexTypeOfType(type: Type, indexType: Type): Type | undefined;
getBaseTypes(type: InterfaceType): BaseType[];
getBaseTypeOfLiteralType(type: Type): Type;
getWidenedType(type: Type): Type;
Expand Down Expand Up @@ -4086,8 +4086,8 @@ namespace ts {
signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): SignatureDeclaration & {typeArguments?: NodeArray<TypeNode>} | undefined;
/* @internal */ signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, tracker?: SymbolTracker): SignatureDeclaration & {typeArguments?: NodeArray<TypeNode>} | undefined; // eslint-disable-line @typescript-eslint/unified-signatures
/** Note that the resulting nodes cannot be checked. */
indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): IndexSignatureDeclaration | undefined;
/* @internal */ indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, tracker?: SymbolTracker): IndexSignatureDeclaration | undefined; // eslint-disable-line @typescript-eslint/unified-signatures
indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, enclosingDeclaration: Node | undefined, flags?: NodeBuilderFlags): IndexSignatureDeclaration | undefined;
/* @internal */ indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, enclosingDeclaration: Node | undefined, flags?: NodeBuilderFlags, tracker?: SymbolTracker): IndexSignatureDeclaration | undefined; // eslint-disable-line @typescript-eslint/unified-signatures
/** Note that the resulting nodes cannot be checked. */
symbolToEntityName(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): EntityName | undefined;
/** Note that the resulting nodes cannot be checked. */
Expand Down Expand Up @@ -4210,9 +4210,10 @@ namespace ts {
/* @internal */ createArrayType(elementType: Type): Type;
/* @internal */ getElementTypeOfArrayType(arrayType: Type): Type | undefined;
/* @internal */ createPromiseType(type: Type): Type;
/* @internal */ createAnonymousType(symbol: Symbol | undefined, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], indexInfos: IndexInfo[] | undefined): Type; // tslint:disable-line unified-signatures
/* @internal */ createAnonymousType(symbol: Symbol | undefined, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo | undefined, numberIndexInfo: IndexInfo | undefined): Type;

/* @internal */ isTypeAssignableTo(source: Type, target: Type): boolean;
/* @internal */ createAnonymousType(symbol: Symbol | undefined, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo | undefined, numberIndexInfo: IndexInfo | undefined): Type;
/* @internal */ createSignature(
declaration: SignatureDeclaration,
typeParameters: readonly TypeParameter[] | undefined,
Expand All @@ -4224,7 +4225,7 @@ namespace ts {
flags: SignatureFlags
): Signature;
/* @internal */ createSymbol(flags: SymbolFlags, name: __String): TransientSymbol;
/* @internal */ createIndexInfo(type: Type, isReadonly: boolean, declaration?: SignatureDeclaration): IndexInfo;
/* @internal */ createIndexInfo(indexType: Type, type: Type, isReadonly: boolean, declaration?: IndexSignatureDeclaration): IndexInfo;
/* @internal */ isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult;
/* @internal */ tryFindAmbientModule(moduleName: string): Symbol | undefined;
/* @internal */ tryFindAmbientModuleWithoutAugmentations(moduleName: string): Symbol | undefined;
Expand Down Expand Up @@ -5239,8 +5240,7 @@ namespace ts {
/* @internal */ properties?: Symbol[]; // Properties
/* @internal */ callSignatures?: readonly Signature[]; // Call signatures of type
/* @internal */ constructSignatures?: readonly Signature[]; // Construct signatures of type
/* @internal */ stringIndexInfo?: IndexInfo; // String indexing info
/* @internal */ numberIndexInfo?: IndexInfo; // Numeric indexing info
/* @internal */ indexInfos?: readonly IndexInfo[]; // Index infos
/* @internal */ objectTypeWithoutAbstractConstructSignatures?: ObjectType;
}

Expand All @@ -5265,8 +5265,7 @@ namespace ts {
declaredProperties: Symbol[]; // Declared members
declaredCallSignatures: Signature[]; // Declared call signatures
declaredConstructSignatures: Signature[]; // Declared construct signatures
declaredStringIndexInfo?: IndexInfo; // Declared string indexing info
declaredNumberIndexInfo?: IndexInfo; // Declared numeric indexing info
declaredIndexInfos?: IndexInfo[]; // Declared indexing infos
}

/**
Expand Down Expand Up @@ -5424,6 +5423,7 @@ namespace ts {
properties: Symbol[]; // Properties
callSignatures: readonly Signature[]; // Call signatures of type
constructSignatures: readonly Signature[]; // Construct signatures of type
indexKeysConstrainedInstantiation?: Type;
}

/* @internal */
Expand Down Expand Up @@ -5649,6 +5649,7 @@ namespace ts {
}

export interface IndexInfo {
indexType: Type;
type: Type;
isReadonly: boolean;
declaration?: IndexSignatureDeclaration;
Expand Down
2 changes: 1 addition & 1 deletion src/harness/fourslashImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -843,7 +843,7 @@ namespace FourSlash {
else {
for (const marker of toArray(options.marker)) {
this.goToMarker(marker);
this.verifyCompletionsWorker(options);
this.verifyCompletionsWorker({ ...options, marker });
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/es5.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ interface PropertyDescriptor {
}

interface PropertyDescriptorMap {
[s: string]: PropertyDescriptor;
[s: string | number | symbol]: PropertyDescriptor;
}

interface Object {
Expand Down
Loading