mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-14 16:56:06 -05:00
Allow intersections to be used as valid types for template literal placeholders (#54188)
This commit is contained in:
committed by
GitHub
parent
cd391b066b
commit
28cd1fbd13
@@ -16457,7 +16457,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
function removeStringLiteralsMatchedByTemplateLiterals(types: Type[]) {
|
||||
const templates = filter(types, t => !!(t.flags & TypeFlags.TemplateLiteral) && isPatternLiteralType(t)) as TemplateLiteralType[];
|
||||
const templates = filter(types, t =>
|
||||
!!(t.flags & TypeFlags.TemplateLiteral) &&
|
||||
isPatternLiteralType(t) &&
|
||||
(t as TemplateLiteralType).types.every(t => !(t.flags & TypeFlags.Intersection) || !areIntersectedTypesAvoidingPrimitiveReduction((t as IntersectionType).types))
|
||||
) as TemplateLiteralType[];
|
||||
if (templates.length) {
|
||||
let i = types.length;
|
||||
while (i > 0) {
|
||||
@@ -16966,8 +16970,12 @@ 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 areIntersectedTypesAvoidingPrimitiveReduction(types: Type[], primitiveFlags = TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt): boolean {
|
||||
if (types.length !== 2) {
|
||||
return false;
|
||||
}
|
||||
const [t1, t2] = types;
|
||||
return !!(t1.flags & primitiveFlags) && t2 === emptyTypeLiteralType || !!(t2.flags & primitiveFlags) && t1 === emptyTypeLiteralType;
|
||||
}
|
||||
|
||||
function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type {
|
||||
@@ -16975,7 +16983,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (!links.resolvedType) {
|
||||
const aliasSymbol = getAliasSymbolForTypeNode(node);
|
||||
const types = map(node.types, getTypeFromTypeNode);
|
||||
const noSupertypeReduction = types.length === 2 && (areIntersectedTypesAvoidingPrimitiveReduction(types[0], types[1]) || areIntersectedTypesAvoidingPrimitiveReduction(types[1], types[0]));
|
||||
const noSupertypeReduction = areIntersectedTypesAvoidingPrimitiveReduction(types);
|
||||
links.resolvedType = getIntersectionType(types, aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol), noSupertypeReduction);
|
||||
}
|
||||
return links.resolvedType;
|
||||
@@ -24362,12 +24370,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (source === target || target.flags & (TypeFlags.Any | TypeFlags.String)) {
|
||||
return true;
|
||||
}
|
||||
if (target.flags & TypeFlags.Intersection) {
|
||||
return every((target as IntersectionType).types, t => t === emptyTypeLiteralType || isValidTypeForTemplateLiteralPlaceholder(source, t));
|
||||
}
|
||||
if (source.flags & TypeFlags.StringLiteral) {
|
||||
const value = (source as StringLiteralType).value;
|
||||
return !!(target.flags & TypeFlags.Number && isValidNumberString(value, /*roundTripOnly*/ false) ||
|
||||
target.flags & TypeFlags.BigInt && isValidBigIntString(value, /*roundTripOnly*/ false) ||
|
||||
target.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && value === (target as IntrinsicType).intrinsicName ||
|
||||
target.flags & TypeFlags.StringMapping && isMemberOfStringMapping(getStringLiteralType(value), target));
|
||||
target.flags & TypeFlags.StringMapping && isMemberOfStringMapping(getStringLiteralType(value), target) ||
|
||||
target.flags & TypeFlags.TemplateLiteral && isTypeMatchedByTemplateLiteralType(source, target as TemplateLiteralType));
|
||||
}
|
||||
if (source.flags & TypeFlags.TemplateLiteral) {
|
||||
const texts = (source as TemplateLiteralType).texts;
|
||||
|
||||
Reference in New Issue
Block a user