mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-11 20:37:46 -05:00
Fixed apparent type of homomorphic mapped type with non-homomorphic instantiation (#56727)
This commit is contained in:
committed by
GitHub
parent
1e00399a38
commit
424b96475e
@@ -2049,6 +2049,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
var noConstraintType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
|
||||
var circularConstraintType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
|
||||
var resolvingDefaultType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
|
||||
var resolvingApparentMappedType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
|
||||
|
||||
var markerSuperType = createTypeParameter();
|
||||
var markerSubType = createTypeParameter();
|
||||
@@ -14459,15 +14460,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
function getApparentTypeOfMappedType(type: MappedType) {
|
||||
return type.resolvedApparentType || (type.resolvedApparentType = getResolvedApparentTypeOfMappedType(type));
|
||||
if (type.resolvedApparentType) {
|
||||
if (type.resolvedApparentType === resolvingApparentMappedType) {
|
||||
return type.resolvedApparentType = type;
|
||||
}
|
||||
return type.resolvedApparentType;
|
||||
}
|
||||
type.resolvedApparentType = resolvingApparentMappedType;
|
||||
return type.resolvedApparentType = getResolvedApparentTypeOfMappedType(type);
|
||||
}
|
||||
|
||||
function getResolvedApparentTypeOfMappedType(type: MappedType) {
|
||||
const typeVariable = getHomomorphicTypeVariable(type);
|
||||
if (typeVariable && !type.declaration.nameType) {
|
||||
const constraint = getConstraintOfTypeParameter(typeVariable);
|
||||
const mappedType = type.target as MappedType || type;
|
||||
const typeVariable = getHomomorphicTypeVariable(mappedType);
|
||||
if (typeVariable && !mappedType.declaration.nameType) {
|
||||
let constraint: Type | undefined;
|
||||
if (!type.target) {
|
||||
constraint = getConstraintOfTypeParameter(typeVariable);
|
||||
}
|
||||
else {
|
||||
const modifiersConstraint = getConstraintOfType(getModifiersTypeFromMappedType(type));
|
||||
if (modifiersConstraint) {
|
||||
constraint = getApparentType(modifiersConstraint);
|
||||
}
|
||||
}
|
||||
if (constraint && everyType(constraint, isArrayOrTupleType)) {
|
||||
return instantiateType(type, prependTypeMapping(typeVariable, constraint, type.mapper));
|
||||
return instantiateType(mappedType, prependTypeMapping(typeVariable, constraint, mappedType.mapper));
|
||||
}
|
||||
}
|
||||
return type;
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
//// [tests/cases/compiler/homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts] ////
|
||||
|
||||
=== homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts ===
|
||||
type HandleOptions<O> = {
|
||||
>HandleOptions : Symbol(HandleOptions, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 0, 0))
|
||||
>O : Symbol(O, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 0, 19))
|
||||
|
||||
[I in keyof O]: {
|
||||
>I : Symbol(I, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 1, 3))
|
||||
>O : Symbol(O, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 0, 19))
|
||||
|
||||
value: O[I];
|
||||
>value : Symbol(value, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 1, 19))
|
||||
>O : Symbol(O, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 0, 19))
|
||||
>I : Symbol(I, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 1, 3))
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
declare function func1<
|
||||
>func1 : Symbol(func1, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 4, 2))
|
||||
|
||||
T extends Record<PropertyKey, readonly any[]>,
|
||||
>T : Symbol(T, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 6, 23))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
>(fields: {
|
||||
>fields : Symbol(fields, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 8, 2))
|
||||
|
||||
[K in keyof T]: {
|
||||
>K : Symbol(K, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 9, 3))
|
||||
>T : Symbol(T, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 6, 23))
|
||||
|
||||
label: string;
|
||||
>label : Symbol(label, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 9, 19))
|
||||
|
||||
options: [...HandleOptions<T[K]>];
|
||||
>options : Symbol(options, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 10, 18))
|
||||
>HandleOptions : Symbol(HandleOptions, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 6, 23))
|
||||
>K : Symbol(K, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 9, 3))
|
||||
|
||||
};
|
||||
}): T;
|
||||
>T : Symbol(T, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 6, 23))
|
||||
|
||||
const result = func1({
|
||||
>result : Symbol(result, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 15, 5))
|
||||
>func1 : Symbol(func1, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 4, 2))
|
||||
|
||||
prop: {
|
||||
>prop : Symbol(prop, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 15, 22))
|
||||
|
||||
label: "first",
|
||||
>label : Symbol(label, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 16, 9))
|
||||
|
||||
options: [
|
||||
>options : Symbol(options, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 17, 19))
|
||||
{
|
||||
value: 123,
|
||||
>value : Symbol(value, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 19, 7))
|
||||
|
||||
},
|
||||
{
|
||||
value: "foo",
|
||||
>value : Symbol(value, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 22, 7))
|
||||
|
||||
},
|
||||
],
|
||||
},
|
||||
other: {
|
||||
>other : Symbol(other, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 26, 4))
|
||||
|
||||
label: "second",
|
||||
>label : Symbol(label, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 27, 10))
|
||||
|
||||
options: [
|
||||
>options : Symbol(options, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 28, 20))
|
||||
{
|
||||
value: "bar",
|
||||
>value : Symbol(value, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 30, 7))
|
||||
|
||||
},
|
||||
{
|
||||
value: true,
|
||||
>value : Symbol(value, Decl(homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts, 33, 7))
|
||||
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,95 @@
|
||||
//// [tests/cases/compiler/homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts] ////
|
||||
|
||||
=== homomorphicMappedTypeWithNonHomomorphicInstantiationSpreadable1.ts ===
|
||||
type HandleOptions<O> = {
|
||||
>HandleOptions : HandleOptions<O>
|
||||
|
||||
[I in keyof O]: {
|
||||
value: O[I];
|
||||
>value : O[I]
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
declare function func1<
|
||||
>func1 : <T extends Record<PropertyKey, readonly any[]>>(fields: { [K in keyof T]: { label: string; options: [...HandleOptions<T[K]>]; }; }) => T
|
||||
|
||||
T extends Record<PropertyKey, readonly any[]>,
|
||||
>(fields: {
|
||||
>fields : { [K in keyof T]: { label: string; options: [...HandleOptions<T[K]>]; }; }
|
||||
|
||||
[K in keyof T]: {
|
||||
label: string;
|
||||
>label : string
|
||||
|
||||
options: [...HandleOptions<T[K]>];
|
||||
>options : [...HandleOptions<T[K]>]
|
||||
|
||||
};
|
||||
}): T;
|
||||
|
||||
const result = func1({
|
||||
>result : { prop: [number, string]; other: [string, boolean]; }
|
||||
>func1({ prop: { label: "first", options: [ { value: 123, }, { value: "foo", }, ], }, other: { label: "second", options: [ { value: "bar", }, { value: true, }, ], },}) : { prop: [number, string]; other: [string, boolean]; }
|
||||
>func1 : <T extends Record<PropertyKey, readonly any[]>>(fields: { [K in keyof T]: { label: string; options: [...HandleOptions<T[K]>]; }; }) => T
|
||||
>{ prop: { label: "first", options: [ { value: 123, }, { value: "foo", }, ], }, other: { label: "second", options: [ { value: "bar", }, { value: true, }, ], },} : { prop: { label: string; options: [{ value: number; }, { value: string; }]; }; other: { label: string; options: [{ value: string; }, { value: true; }]; }; }
|
||||
|
||||
prop: {
|
||||
>prop : { label: string; options: [{ value: number; }, { value: string; }]; }
|
||||
>{ label: "first", options: [ { value: 123, }, { value: "foo", }, ], } : { label: string; options: [{ value: number; }, { value: string; }]; }
|
||||
|
||||
label: "first",
|
||||
>label : string
|
||||
>"first" : "first"
|
||||
|
||||
options: [
|
||||
>options : [{ value: number; }, { value: string; }]
|
||||
>[ { value: 123, }, { value: "foo", }, ] : [{ value: number; }, { value: string; }]
|
||||
{
|
||||
>{ value: 123, } : { value: number; }
|
||||
|
||||
value: 123,
|
||||
>value : number
|
||||
>123 : 123
|
||||
|
||||
},
|
||||
{
|
||||
>{ value: "foo", } : { value: string; }
|
||||
|
||||
value: "foo",
|
||||
>value : string
|
||||
>"foo" : "foo"
|
||||
|
||||
},
|
||||
],
|
||||
},
|
||||
other: {
|
||||
>other : { label: string; options: [{ value: string; }, { value: true; }]; }
|
||||
>{ label: "second", options: [ { value: "bar", }, { value: true, }, ], } : { label: string; options: [{ value: string; }, { value: true; }]; }
|
||||
|
||||
label: "second",
|
||||
>label : string
|
||||
>"second" : "second"
|
||||
|
||||
options: [
|
||||
>options : [{ value: string; }, { value: true; }]
|
||||
>[ { value: "bar", }, { value: true, }, ] : [{ value: string; }, { value: true; }]
|
||||
{
|
||||
>{ value: "bar", } : { value: string; }
|
||||
|
||||
value: "bar",
|
||||
>value : string
|
||||
>"bar" : "bar"
|
||||
|
||||
},
|
||||
{
|
||||
>{ value: true, } : { value: true; }
|
||||
|
||||
value: true,
|
||||
>value : true
|
||||
>true : true
|
||||
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
// @strict: true
|
||||
// @noEmit: true
|
||||
|
||||
type HandleOptions<O> = {
|
||||
[I in keyof O]: {
|
||||
value: O[I];
|
||||
};
|
||||
};
|
||||
|
||||
declare function func1<
|
||||
T extends Record<PropertyKey, readonly any[]>,
|
||||
>(fields: {
|
||||
[K in keyof T]: {
|
||||
label: string;
|
||||
options: [...HandleOptions<T[K]>];
|
||||
};
|
||||
}): T;
|
||||
|
||||
const result = func1({
|
||||
prop: {
|
||||
label: "first",
|
||||
options: [
|
||||
{
|
||||
value: 123,
|
||||
},
|
||||
{
|
||||
value: "foo",
|
||||
},
|
||||
],
|
||||
},
|
||||
other: {
|
||||
label: "second",
|
||||
options: [
|
||||
{
|
||||
value: "bar",
|
||||
},
|
||||
{
|
||||
value: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user