Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9f33bf1

Browse files
TypeScript Botahejlsberg
TypeScript Bot
andauthored
🤖 Pick PR#58098 (Fix constraints of nested homomorph...) into release-5.4 (#58118)
Co-authored-by: Anders Hejlsberg <andersh@microsoft.com>
1 parent71b2f84 commit9f33bf1

File tree

4 files changed

+103
-7
lines changed

4 files changed

+103
-7
lines changed

‎src/compiler/checker.ts‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14552,16 +14552,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1455214552
return type.resolvedApparentType || (type.resolvedApparentType = getResolvedApparentTypeOfMappedType(type));
1455314553
}
1455414554

14555-
function getResolvedApparentTypeOfMappedType(type: MappedType) {
14555+
function getResolvedApparentTypeOfMappedType(type: MappedType): Type {
1455614556
const target = (type.target ?? type) as MappedType;
1455714557
const typeVariable = getHomomorphicTypeVariable(target);
1455814558
if (typeVariable && !target.declaration.nameType) {
14559-
const constraint = getConstraintTypeFromMappedType(type);
14560-
if (constraint.flags & TypeFlags.Index) {
14561-
const baseConstraint = getBaseConstraintOfType((constraint as IndexType).type);
14562-
if (baseConstraint && everyType(baseConstraint, t => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) {
14563-
return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper));
14564-
}
14559+
// We have a homomorphic mapped type or an instantiation of a homomorphic mapped type, i.e. a type
14560+
// of the form { [P in keyof T]: X }. Obtain the modifiers type (the T of the keyof T), and if it is
14561+
// another generic mapped type, recursively obtain its apparent type. Otherwise, obtain its base
14562+
// constraint. Then, if every constituent of the base constraint is an array or tuple type, apply
14563+
// this mapped type to the base constraint. It is safe to recurse when the modifiers type is a
14564+
// mapped type because we protect again circular constraints in getTypeFromMappedTypeNode.
14565+
const modifiersType = getModifiersTypeFromMappedType(type);
14566+
const baseConstraint = isGenericMappedType(modifiersType) ? getApparentTypeOfMappedType(modifiersType) : getBaseConstraintOfType(modifiersType);
14567+
if (baseConstraint && everyType(baseConstraint, t => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) {
14568+
return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper));
1456514569
}
1456614570
}
1456714571
return type;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//// [tests/cases/compiler/homomorphicMappedTypeNesting.ts] ////
2+
3+
=== homomorphicMappedTypeNesting.ts ===
4+
// Repro from #58060
5+
6+
type Box<T extends string> = { v: T };
7+
>Box : Symbol(Box, Decl(homomorphicMappedTypeNesting.ts, 0, 0))
8+
>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 2, 9))
9+
>v : Symbol(v, Decl(homomorphicMappedTypeNesting.ts, 2, 30))
10+
>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 2, 9))
11+
12+
type Test<T extends string[]> = T
13+
>Test : Symbol(Test, Decl(homomorphicMappedTypeNesting.ts, 2, 38))
14+
>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 4, 10))
15+
>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 4, 10))
16+
17+
type UnboxArray<T> = {
18+
>UnboxArray : Symbol(UnboxArray, Decl(homomorphicMappedTypeNesting.ts, 4, 33))
19+
>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 6, 16))
20+
21+
[K in keyof T]: T[K] extends Box<infer R> ? R : never;
22+
>K : Symbol(K, Decl(homomorphicMappedTypeNesting.ts, 7, 5))
23+
>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 6, 16))
24+
>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 6, 16))
25+
>K : Symbol(K, Decl(homomorphicMappedTypeNesting.ts, 7, 5))
26+
>Box : Symbol(Box, Decl(homomorphicMappedTypeNesting.ts, 0, 0))
27+
>R : Symbol(R, Decl(homomorphicMappedTypeNesting.ts, 7, 42))
28+
>R : Symbol(R, Decl(homomorphicMappedTypeNesting.ts, 7, 42))
29+
30+
};
31+
32+
type Identity<T> = { [K in keyof T]: T[K] };
33+
>Identity : Symbol(Identity, Decl(homomorphicMappedTypeNesting.ts, 8, 2))
34+
>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 10, 14))
35+
>K : Symbol(K, Decl(homomorphicMappedTypeNesting.ts, 10, 22))
36+
>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 10, 14))
37+
>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 10, 14))
38+
>K : Symbol(K, Decl(homomorphicMappedTypeNesting.ts, 10, 22))
39+
40+
declare function fnBad<T extends Array<Box<string>>>(...args: T): Test<Identity<UnboxArray<T>>>;
41+
>fnBad : Symbol(fnBad, Decl(homomorphicMappedTypeNesting.ts, 10, 44))
42+
>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 12, 23))
43+
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
44+
>Box : Symbol(Box, Decl(homomorphicMappedTypeNesting.ts, 0, 0))
45+
>args : Symbol(args, Decl(homomorphicMappedTypeNesting.ts, 12, 53))
46+
>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 12, 23))
47+
>Test : Symbol(Test, Decl(homomorphicMappedTypeNesting.ts, 2, 38))
48+
>Identity : Symbol(Identity, Decl(homomorphicMappedTypeNesting.ts, 8, 2))
49+
>UnboxArray : Symbol(UnboxArray, Decl(homomorphicMappedTypeNesting.ts, 4, 33))
50+
>T : Symbol(T, Decl(homomorphicMappedTypeNesting.ts, 12, 23))
51+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//// [tests/cases/compiler/homomorphicMappedTypeNesting.ts] ////
2+
3+
=== homomorphicMappedTypeNesting.ts ===
4+
// Repro from #58060
5+
6+
type Box<T extends string> = { v: T };
7+
>Box : Box<T>
8+
>v : T
9+
10+
type Test<T extends string[]> = T
11+
>Test : T
12+
13+
type UnboxArray<T> = {
14+
>UnboxArray : UnboxArray<T>
15+
16+
[K in keyof T]: T[K] extends Box<infer R> ? R : never;
17+
};
18+
19+
type Identity<T> = { [K in keyof T]: T[K] };
20+
>Identity : Identity<T>
21+
22+
declare function fnBad<T extends Array<Box<string>>>(...args: T): Test<Identity<UnboxArray<T>>>;
23+
>fnBad : <T extends Box<string>[]>(...args: T) => Test<Identity<UnboxArray<T>>>
24+
>args : T
25+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@strict: true
2+
//@noEmit: true
3+
4+
// Repro from #58060
5+
6+
typeBox<Textendsstring>={v:T};
7+
8+
typeTest<Textendsstring[]>=T
9+
10+
typeUnboxArray<T>={
11+
[KinkeyofT]:T[K]extendsBox<inferR> ?R :never;
12+
};
13+
14+
typeIdentity<T>={[KinkeyofT]:T[K]};
15+
16+
declarefunctionfnBad<TextendsArray<Box<string>>>(...args:T):Test<Identity<UnboxArray<T>>>;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp