Skip to content

Commit 7f11456

Browse files
TypeScript Botahejlsberg
TypeScript Bot
andauthored
🤖 Pick PR #57751 (Exclude generic string-like types f...) into release-5.4 (#57753)
Co-authored-by: Anders Hejlsberg <[email protected]>
1 parent 42bb138 commit 7f11456

4 files changed

+161
-2
lines changed

‎src/compiler/checker.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -17624,7 +17624,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1762417624
const typeVarIndex = typeSet[0].flags & TypeFlags.TypeVariable ? 0 : 1;
1762517625
const typeVariable = typeSet[typeVarIndex];
1762617626
const primitiveType = typeSet[1 - typeVarIndex];
17627-
if (typeVariable.flags & TypeFlags.TypeVariable && (primitiveType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive) || includes & TypeFlags.IncludesEmptyObject)) {
17627+
if (
17628+
typeVariable.flags & TypeFlags.TypeVariable &&
17629+
(primitiveType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive) && !isGenericStringLikeType(primitiveType) || includes & TypeFlags.IncludesEmptyObject)
17630+
) {
1762817631
// We have an intersection T & P or P & T, where T is a type variable and P is a primitive type, the object type, or {}.
1762917632
const constraint = getBaseConstraintOfType(typeVariable);
1763017633
// Check that T's constraint is similarly composed of primitive types, the object type, or {}.
@@ -18374,6 +18377,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1837418377
!!(type.flags & TypeFlags.StringMapping) && isPatternLiteralPlaceholderType((type as StringMappingType).type);
1837518378
}
1837618379

18380+
function isGenericStringLikeType(type: Type) {
18381+
return !!(type.flags & (TypeFlags.TemplateLiteral | TypeFlags.StringMapping)) && !isPatternLiteralType(type);
18382+
}
18383+
1837718384
function isGenericType(type: Type): boolean {
1837818385
return !!getGenericObjectFlags(type);
1837918386
}
@@ -18402,7 +18409,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1840218409
return (type as SubstitutionType).objectFlags & ObjectFlags.IsGenericType;
1840318410
}
1840418411
return (type.flags & TypeFlags.InstantiableNonPrimitive || isGenericMappedType(type) || isGenericTupleType(type) ? ObjectFlags.IsGenericObjectType : 0) |
18405-
(type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) && !isPatternLiteralType(type) ? ObjectFlags.IsGenericIndexType : 0);
18412+
(type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.Index) || isGenericStringLikeType(type) ? ObjectFlags.IsGenericIndexType : 0);
1840618413
}
1840718414

1840818415
function getSimplifiedType(type: Type, writing: boolean): Type {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//// [tests/cases/compiler/intersectionReductionGenericStringLikeType.ts] ////
2+
3+
=== intersectionReductionGenericStringLikeType.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/57736
5+
6+
type obj = {
7+
>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0))
8+
9+
foo: 1;
10+
>foo : Symbol(foo, Decl(intersectionReductionGenericStringLikeType.ts, 2, 12))
11+
12+
bar: 2;
13+
>bar : Symbol(bar, Decl(intersectionReductionGenericStringLikeType.ts, 3, 11))
14+
15+
};
16+
17+
type keyContaining1<
18+
>keyContaining1 : Symbol(keyContaining1, Decl(intersectionReductionGenericStringLikeType.ts, 5, 2))
19+
20+
str extends string,
21+
>str : Symbol(str, Decl(intersectionReductionGenericStringLikeType.ts, 7, 20))
22+
23+
keys extends keyof obj = keyof obj,
24+
>keys : Symbol(keys, Decl(intersectionReductionGenericStringLikeType.ts, 8, 23))
25+
>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0))
26+
>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0))
27+
28+
> = keys extends infer key extends keyof obj
29+
>keys : Symbol(keys, Decl(intersectionReductionGenericStringLikeType.ts, 8, 23))
30+
>key : Symbol(key, Decl(intersectionReductionGenericStringLikeType.ts, 10, 22))
31+
>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0))
32+
33+
? key extends `${string}${str}${string}`
34+
>key : Symbol(key, Decl(intersectionReductionGenericStringLikeType.ts, 10, 22))
35+
>str : Symbol(str, Decl(intersectionReductionGenericStringLikeType.ts, 7, 20))
36+
37+
? obj[key]
38+
>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0))
39+
>key : Symbol(key, Decl(intersectionReductionGenericStringLikeType.ts, 10, 22))
40+
41+
: never
42+
: never;
43+
44+
type _1 = keyContaining1<"foo">; // 1
45+
>_1 : Symbol(_1, Decl(intersectionReductionGenericStringLikeType.ts, 14, 12))
46+
>keyContaining1 : Symbol(keyContaining1, Decl(intersectionReductionGenericStringLikeType.ts, 5, 2))
47+
48+
type keyContaining2<
49+
>keyContaining2 : Symbol(keyContaining2, Decl(intersectionReductionGenericStringLikeType.ts, 16, 32))
50+
51+
str extends string,
52+
>str : Symbol(str, Decl(intersectionReductionGenericStringLikeType.ts, 18, 20))
53+
54+
keys extends keyof obj = keyof obj,
55+
>keys : Symbol(keys, Decl(intersectionReductionGenericStringLikeType.ts, 19, 23))
56+
>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0))
57+
>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0))
58+
59+
> = keys extends keys
60+
>keys : Symbol(keys, Decl(intersectionReductionGenericStringLikeType.ts, 19, 23))
61+
>keys : Symbol(keys, Decl(intersectionReductionGenericStringLikeType.ts, 19, 23))
62+
63+
? keys extends `${string}${str}${string}`
64+
>keys : Symbol(keys, Decl(intersectionReductionGenericStringLikeType.ts, 19, 23))
65+
>str : Symbol(str, Decl(intersectionReductionGenericStringLikeType.ts, 18, 20))
66+
67+
? obj[keys]
68+
>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0))
69+
>keys : Symbol(keys, Decl(intersectionReductionGenericStringLikeType.ts, 19, 23))
70+
71+
: never
72+
: never;
73+
74+
type _2 = keyContaining2<"foo">; // 1
75+
>_2 : Symbol(_2, Decl(intersectionReductionGenericStringLikeType.ts, 25, 12))
76+
>keyContaining2 : Symbol(keyContaining2, Decl(intersectionReductionGenericStringLikeType.ts, 16, 32))
77+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//// [tests/cases/compiler/intersectionReductionGenericStringLikeType.ts] ////
2+
3+
=== intersectionReductionGenericStringLikeType.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/57736
5+
6+
type obj = {
7+
>obj : { foo: 1; bar: 2; }
8+
9+
foo: 1;
10+
>foo : 1
11+
12+
bar: 2;
13+
>bar : 2
14+
15+
};
16+
17+
type keyContaining1<
18+
>keyContaining1 : keyContaining1<str, keys>
19+
20+
str extends string,
21+
keys extends keyof obj = keyof obj,
22+
> = keys extends infer key extends keyof obj
23+
? key extends `${string}${str}${string}`
24+
? obj[key]
25+
: never
26+
: never;
27+
28+
type _1 = keyContaining1<"foo">; // 1
29+
>_1 : 1
30+
31+
type keyContaining2<
32+
>keyContaining2 : keyContaining2<str, keys>
33+
34+
str extends string,
35+
keys extends keyof obj = keyof obj,
36+
> = keys extends keys
37+
? keys extends `${string}${str}${string}`
38+
? obj[keys]
39+
: never
40+
: never;
41+
42+
type _2 = keyContaining2<"foo">; // 1
43+
>_2 : 1
44+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
// https://github.com/microsoft/TypeScript/issues/57736
5+
6+
type obj = {
7+
foo: 1;
8+
bar: 2;
9+
};
10+
11+
type keyContaining1<
12+
str extends string,
13+
keys extends keyof obj = keyof obj,
14+
> = keys extends infer key extends keyof obj
15+
? key extends `${string}${str}${string}`
16+
? obj[key]
17+
: never
18+
: never;
19+
20+
type _1 = keyContaining1<"foo">; // 1
21+
22+
type keyContaining2<
23+
str extends string,
24+
keys extends keyof obj = keyof obj,
25+
> = keys extends keys
26+
? keys extends `${string}${str}${string}`
27+
? obj[keys]
28+
: never
29+
: never;
30+
31+
type _2 = keyContaining2<"foo">; // 1

0 commit comments

Comments
 (0)