mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Make special intersections order-independent (#52782)
This commit is contained in:
parent
3f4d16a25e
commit
88adf8014b
@ -16766,12 +16766,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return reduceLeft(types, (n, t) => n + getConstituentCount(t), 0);
|
||||
}
|
||||
|
||||
function areIntersectedTypesAvoidingPrimitiveReduction(t1: Type, t2: Type) {
|
||||
return !!(t1.flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) && t2 === emptyTypeLiteralType;
|
||||
}
|
||||
|
||||
function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type {
|
||||
const links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
const aliasSymbol = getAliasSymbolForTypeNode(node);
|
||||
const types = map(node.types, getTypeFromTypeNode);
|
||||
const noSupertypeReduction = types.length === 2 && !!(types[0].flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) && types[1] === emptyTypeLiteralType;
|
||||
const noSupertypeReduction = types.length === 2 && (areIntersectedTypesAvoidingPrimitiveReduction(types[0], types[1]) || areIntersectedTypesAvoidingPrimitiveReduction(types[1], types[0]));
|
||||
links.resolvedType = getIntersectionType(types, aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol), noSupertypeReduction);
|
||||
}
|
||||
return links.resolvedType;
|
||||
|
||||
@ -2165,6 +2165,10 @@ export function isStringOrRegularExpressionOrTemplateLiteral(kind: SyntaxKind):
|
||||
return false;
|
||||
}
|
||||
|
||||
function areIntersectedTypesAvoidingStringReduction(checker: TypeChecker, t1: Type, t2: Type) {
|
||||
return !!(t1.flags & TypeFlags.String) && checker.isEmptyAnonymousObjectType(t2);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isStringAndEmptyAnonymousObjectIntersection(type: Type) {
|
||||
if (!type.isIntersection()) {
|
||||
@ -2172,8 +2176,8 @@ export function isStringAndEmptyAnonymousObjectIntersection(type: Type) {
|
||||
}
|
||||
|
||||
const { types, checker } = type;
|
||||
return types.length === 2
|
||||
&& (types[0].flags & TypeFlags.String) && checker.isEmptyAnonymousObjectType(types[1]);
|
||||
return types.length === 2 &&
|
||||
(areIntersectedTypesAvoidingStringReduction(checker, types[0], types[1]) || areIntersectedTypesAvoidingStringReduction(checker, types[1], types[0]));
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
||||
@ -6,7 +6,7 @@ tests/cases/conformance/types/unknown/unknownControlFlow.ts(293,5): error TS2345
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/unknown/unknownControlFlow.ts (5 errors) ====
|
||||
type T01 = {} & string; // string
|
||||
type T01 = {} & string; // {} & string
|
||||
type T02 = {} & 'a'; // 'a'
|
||||
type T03 = {} & object; // object
|
||||
type T04 = {} & { x: number }; // { x: number }
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//// [unknownControlFlow.ts]
|
||||
type T01 = {} & string; // string
|
||||
type T01 = {} & string; // {} & string
|
||||
type T02 = {} & 'a'; // 'a'
|
||||
type T03 = {} & object; // object
|
||||
type T04 = {} & { x: number }; // { x: number }
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
=== tests/cases/conformance/types/unknown/unknownControlFlow.ts ===
|
||||
type T01 = {} & string; // string
|
||||
type T01 = {} & string; // {} & string
|
||||
>T01 : Symbol(T01, Decl(unknownControlFlow.ts, 0, 0))
|
||||
|
||||
type T02 = {} & 'a'; // 'a'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
=== tests/cases/conformance/types/unknown/unknownControlFlow.ts ===
|
||||
type T01 = {} & string; // string
|
||||
>T01 : string
|
||||
type T01 = {} & string; // {} & string
|
||||
>T01 : {} & string
|
||||
|
||||
type T02 = {} & 'a'; // 'a'
|
||||
>T02 : "a"
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// @strict: true
|
||||
// @declaration: true
|
||||
|
||||
type T01 = {} & string; // string
|
||||
type T01 = {} & string; // {} & string
|
||||
type T02 = {} & 'a'; // 'a'
|
||||
type T03 = {} & object; // object
|
||||
type T04 = {} & { x: number }; // { x: number }
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
//
|
||||
//// declare function a(arg: 'test' | (string & {})): void
|
||||
//// a('/*1*/')
|
||||
//// declare function b(arg: 'test' | ({} & string)): void
|
||||
//// b('/*2*/')
|
||||
|
||||
verify.completions({ marker: ["1", "2"], exact: ["test"] });
|
||||
Loading…
x
Reference in New Issue
Block a user