mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-20 10:29:36 -06:00
Resolve contextual computed properties with non-bindable names (#51915)
This commit is contained in:
parent
73a98aee00
commit
58ee54c2aa
@ -28997,6 +28997,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const symbol = getSymbolOfDeclaration(element);
|
||||
return getTypeOfPropertyOfContextualType(type, symbol.escapedName, getSymbolLinks(symbol).nameType);
|
||||
}
|
||||
if (hasDynamicName(element)) {
|
||||
const name = getNameOfDeclaration(element);
|
||||
if (name && isComputedPropertyName(name)) {
|
||||
const exprType = checkExpression(name.expression);
|
||||
const propType = isTypeUsableAsPropertyName(exprType) && getTypeOfPropertyOfContextualType(type, getPropertyNameFromType(exprType));
|
||||
if (propType) {
|
||||
return propType;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (element.name) {
|
||||
const nameType = getLiteralTypeFromPropertyName(element.name);
|
||||
// We avoid calling getApplicableIndexInfo here because it performs potentially expensive intersection reduction.
|
||||
|
||||
@ -0,0 +1,98 @@
|
||||
=== tests/cases/compiler/contextualComputedNonBindablePropertyType.ts ===
|
||||
// repro #51906
|
||||
|
||||
declare function testD(): "d";
|
||||
>testD : Symbol(testD, Decl(contextualComputedNonBindablePropertyType.ts, 0, 0))
|
||||
|
||||
declare function forceMatch<T>(matched: {
|
||||
>forceMatch : Symbol(forceMatch, Decl(contextualComputedNonBindablePropertyType.ts, 2, 30))
|
||||
>T : Symbol(T, Decl(contextualComputedNonBindablePropertyType.ts, 4, 28))
|
||||
>matched : Symbol(matched, Decl(contextualComputedNonBindablePropertyType.ts, 4, 31))
|
||||
|
||||
[key in keyof T]: key;
|
||||
>key : Symbol(key, Decl(contextualComputedNonBindablePropertyType.ts, 5, 3))
|
||||
>T : Symbol(T, Decl(contextualComputedNonBindablePropertyType.ts, 4, 28))
|
||||
>key : Symbol(key, Decl(contextualComputedNonBindablePropertyType.ts, 5, 3))
|
||||
|
||||
}): void;
|
||||
|
||||
forceMatch({
|
||||
>forceMatch : Symbol(forceMatch, Decl(contextualComputedNonBindablePropertyType.ts, 2, 30))
|
||||
|
||||
[testD()]: "d",
|
||||
>[testD()] : Symbol([testD()], Decl(contextualComputedNonBindablePropertyType.ts, 8, 12))
|
||||
>testD : Symbol(testD, Decl(contextualComputedNonBindablePropertyType.ts, 0, 0))
|
||||
|
||||
});
|
||||
|
||||
declare function forceMatch2<T>(matched: {
|
||||
>forceMatch2 : Symbol(forceMatch2, Decl(contextualComputedNonBindablePropertyType.ts, 10, 3))
|
||||
>T : Symbol(T, Decl(contextualComputedNonBindablePropertyType.ts, 12, 29))
|
||||
>matched : Symbol(matched, Decl(contextualComputedNonBindablePropertyType.ts, 12, 32))
|
||||
|
||||
[key in keyof T]: ({ key }: { key: key }) => void;
|
||||
>key : Symbol(key, Decl(contextualComputedNonBindablePropertyType.ts, 13, 3))
|
||||
>T : Symbol(T, Decl(contextualComputedNonBindablePropertyType.ts, 12, 29))
|
||||
>key : Symbol(key, Decl(contextualComputedNonBindablePropertyType.ts, 13, 22))
|
||||
>key : Symbol(key, Decl(contextualComputedNonBindablePropertyType.ts, 13, 31))
|
||||
>key : Symbol(key, Decl(contextualComputedNonBindablePropertyType.ts, 13, 3))
|
||||
|
||||
}): void;
|
||||
|
||||
forceMatch2({
|
||||
>forceMatch2 : Symbol(forceMatch2, Decl(contextualComputedNonBindablePropertyType.ts, 10, 3))
|
||||
|
||||
[testD()]: ({ key }) => {},
|
||||
>[testD()] : Symbol([testD()], Decl(contextualComputedNonBindablePropertyType.ts, 16, 13))
|
||||
>testD : Symbol(testD, Decl(contextualComputedNonBindablePropertyType.ts, 0, 0))
|
||||
>key : Symbol(key, Decl(contextualComputedNonBindablePropertyType.ts, 17, 15))
|
||||
|
||||
});
|
||||
|
||||
// repro #52954
|
||||
|
||||
type Original = { foo: 'expects a string literal', baz: boolean, bar: number }
|
||||
>Original : Symbol(Original, Decl(contextualComputedNonBindablePropertyType.ts, 18, 3))
|
||||
>foo : Symbol(foo, Decl(contextualComputedNonBindablePropertyType.ts, 22, 17))
|
||||
>baz : Symbol(baz, Decl(contextualComputedNonBindablePropertyType.ts, 22, 50))
|
||||
>bar : Symbol(bar, Decl(contextualComputedNonBindablePropertyType.ts, 22, 64))
|
||||
|
||||
type Mapped = {
|
||||
>Mapped : Symbol(Mapped, Decl(contextualComputedNonBindablePropertyType.ts, 22, 78))
|
||||
|
||||
[prop in keyof Original]: (arg: Original[prop]) => Original[prop]
|
||||
>prop : Symbol(prop, Decl(contextualComputedNonBindablePropertyType.ts, 25, 3))
|
||||
>Original : Symbol(Original, Decl(contextualComputedNonBindablePropertyType.ts, 18, 3))
|
||||
>arg : Symbol(arg, Decl(contextualComputedNonBindablePropertyType.ts, 25, 29))
|
||||
>Original : Symbol(Original, Decl(contextualComputedNonBindablePropertyType.ts, 18, 3))
|
||||
>prop : Symbol(prop, Decl(contextualComputedNonBindablePropertyType.ts, 25, 3))
|
||||
>Original : Symbol(Original, Decl(contextualComputedNonBindablePropertyType.ts, 18, 3))
|
||||
>prop : Symbol(prop, Decl(contextualComputedNonBindablePropertyType.ts, 25, 3))
|
||||
}
|
||||
|
||||
const propSelector = <propName extends string>(propName: propName): propName => propName;
|
||||
>propSelector : Symbol(propSelector, Decl(contextualComputedNonBindablePropertyType.ts, 28, 5))
|
||||
>propName : Symbol(propName, Decl(contextualComputedNonBindablePropertyType.ts, 28, 23), Decl(contextualComputedNonBindablePropertyType.ts, 28, 48))
|
||||
>propName : Symbol(propName, Decl(contextualComputedNonBindablePropertyType.ts, 28, 23), Decl(contextualComputedNonBindablePropertyType.ts, 28, 48))
|
||||
>propName : Symbol(propName, Decl(contextualComputedNonBindablePropertyType.ts, 28, 23), Decl(contextualComputedNonBindablePropertyType.ts, 28, 48))
|
||||
>propName : Symbol(propName, Decl(contextualComputedNonBindablePropertyType.ts, 28, 23), Decl(contextualComputedNonBindablePropertyType.ts, 28, 48))
|
||||
>propName : Symbol(propName, Decl(contextualComputedNonBindablePropertyType.ts, 28, 23), Decl(contextualComputedNonBindablePropertyType.ts, 28, 48))
|
||||
|
||||
const unexpectedlyFailingExample: Mapped = {
|
||||
>unexpectedlyFailingExample : Symbol(unexpectedlyFailingExample, Decl(contextualComputedNonBindablePropertyType.ts, 30, 5))
|
||||
>Mapped : Symbol(Mapped, Decl(contextualComputedNonBindablePropertyType.ts, 22, 78))
|
||||
|
||||
foo: (arg) => 'expects a string literal',
|
||||
>foo : Symbol(foo, Decl(contextualComputedNonBindablePropertyType.ts, 30, 44))
|
||||
>arg : Symbol(arg, Decl(contextualComputedNonBindablePropertyType.ts, 31, 8))
|
||||
|
||||
baz: (arg) => true,
|
||||
>baz : Symbol(baz, Decl(contextualComputedNonBindablePropertyType.ts, 31, 43))
|
||||
>arg : Symbol(arg, Decl(contextualComputedNonBindablePropertyType.ts, 32, 8))
|
||||
|
||||
[propSelector('bar')]: (arg) => 51345
|
||||
>[propSelector('bar')] : Symbol([propSelector('bar')], Decl(contextualComputedNonBindablePropertyType.ts, 32, 21))
|
||||
>propSelector : Symbol(propSelector, Decl(contextualComputedNonBindablePropertyType.ts, 28, 5))
|
||||
>arg : Symbol(arg, Decl(contextualComputedNonBindablePropertyType.ts, 33, 26))
|
||||
}
|
||||
|
||||
@ -0,0 +1,97 @@
|
||||
=== tests/cases/compiler/contextualComputedNonBindablePropertyType.ts ===
|
||||
// repro #51906
|
||||
|
||||
declare function testD(): "d";
|
||||
>testD : () => "d"
|
||||
|
||||
declare function forceMatch<T>(matched: {
|
||||
>forceMatch : <T>(matched: { [key in keyof T]: key; }) => void
|
||||
>matched : { [key in keyof T]: key; }
|
||||
|
||||
[key in keyof T]: key;
|
||||
}): void;
|
||||
|
||||
forceMatch({
|
||||
>forceMatch({ [testD()]: "d",}) : void
|
||||
>forceMatch : <T>(matched: { [key in keyof T]: key; }) => void
|
||||
>{ [testD()]: "d",} : { d: "d"; }
|
||||
|
||||
[testD()]: "d",
|
||||
>[testD()] : "d"
|
||||
>testD() : "d"
|
||||
>testD : () => "d"
|
||||
>"d" : "d"
|
||||
|
||||
});
|
||||
|
||||
declare function forceMatch2<T>(matched: {
|
||||
>forceMatch2 : <T>(matched: { [key in keyof T]: ({ key }: { key: key; }) => void; }) => void
|
||||
>matched : { [key in keyof T]: ({ key }: { key: key; }) => void; }
|
||||
|
||||
[key in keyof T]: ({ key }: { key: key }) => void;
|
||||
>key : key
|
||||
>key : key
|
||||
|
||||
}): void;
|
||||
|
||||
forceMatch2({
|
||||
>forceMatch2({ [testD()]: ({ key }) => {},}) : void
|
||||
>forceMatch2 : <T>(matched: { [key in keyof T]: ({ key }: { key: key; }) => void; }) => void
|
||||
>{ [testD()]: ({ key }) => {},} : { d: ({ key }: { key: "d"; }) => void; }
|
||||
|
||||
[testD()]: ({ key }) => {},
|
||||
>[testD()] : ({ key }: { key: "d"; }) => void
|
||||
>testD() : "d"
|
||||
>testD : () => "d"
|
||||
>({ key }) => {} : ({ key }: { key: "d"; }) => void
|
||||
>key : "d"
|
||||
|
||||
});
|
||||
|
||||
// repro #52954
|
||||
|
||||
type Original = { foo: 'expects a string literal', baz: boolean, bar: number }
|
||||
>Original : { foo: 'expects a string literal'; baz: boolean; bar: number; }
|
||||
>foo : "expects a string literal"
|
||||
>baz : boolean
|
||||
>bar : number
|
||||
|
||||
type Mapped = {
|
||||
>Mapped : { foo: (arg: "expects a string literal") => "expects a string literal"; baz: (arg: boolean) => boolean; bar: (arg: number) => number; }
|
||||
|
||||
[prop in keyof Original]: (arg: Original[prop]) => Original[prop]
|
||||
>arg : Original[prop]
|
||||
}
|
||||
|
||||
const propSelector = <propName extends string>(propName: propName): propName => propName;
|
||||
>propSelector : <propName extends string>(propName: propName) => propName
|
||||
><propName extends string>(propName: propName): propName => propName : <propName extends string>(propName: propName) => propName
|
||||
>propName : propName
|
||||
>propName : propName
|
||||
|
||||
const unexpectedlyFailingExample: Mapped = {
|
||||
>unexpectedlyFailingExample : Mapped
|
||||
>{ foo: (arg) => 'expects a string literal', baz: (arg) => true, [propSelector('bar')]: (arg) => 51345} : { foo: (arg: "expects a string literal") => "expects a string literal"; baz: (arg: boolean) => true; bar: (arg: number) => number; }
|
||||
|
||||
foo: (arg) => 'expects a string literal',
|
||||
>foo : (arg: "expects a string literal") => "expects a string literal"
|
||||
>(arg) => 'expects a string literal' : (arg: "expects a string literal") => "expects a string literal"
|
||||
>arg : "expects a string literal"
|
||||
>'expects a string literal' : "expects a string literal"
|
||||
|
||||
baz: (arg) => true,
|
||||
>baz : (arg: boolean) => true
|
||||
>(arg) => true : (arg: boolean) => true
|
||||
>arg : boolean
|
||||
>true : true
|
||||
|
||||
[propSelector('bar')]: (arg) => 51345
|
||||
>[propSelector('bar')] : (arg: number) => number
|
||||
>propSelector('bar') : "bar"
|
||||
>propSelector : <propName extends string>(propName: propName) => propName
|
||||
>'bar' : "bar"
|
||||
>(arg) => 51345 : (arg: number) => number
|
||||
>arg : number
|
||||
>51345 : 51345
|
||||
}
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
// @noEmit: true
|
||||
// @strict: true
|
||||
|
||||
// repro #51906
|
||||
|
||||
declare function testD(): "d";
|
||||
|
||||
declare function forceMatch<T>(matched: {
|
||||
[key in keyof T]: key;
|
||||
}): void;
|
||||
|
||||
forceMatch({
|
||||
[testD()]: "d",
|
||||
});
|
||||
|
||||
declare function forceMatch2<T>(matched: {
|
||||
[key in keyof T]: ({ key }: { key: key }) => void;
|
||||
}): void;
|
||||
|
||||
forceMatch2({
|
||||
[testD()]: ({ key }) => {},
|
||||
});
|
||||
|
||||
// repro #52954
|
||||
|
||||
type Original = { foo: 'expects a string literal', baz: boolean, bar: number }
|
||||
|
||||
type Mapped = {
|
||||
[prop in keyof Original]: (arg: Original[prop]) => Original[prop]
|
||||
}
|
||||
|
||||
const propSelector = <propName extends string>(propName: propName): propName => propName;
|
||||
|
||||
const unexpectedlyFailingExample: Mapped = {
|
||||
foo: (arg) => 'expects a string literal',
|
||||
baz: (arg) => true,
|
||||
[propSelector('bar')]: (arg) => 51345
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user