diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c693af4f0ac..fdffe0aca7f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12210,8 +12210,7 @@ namespace ts { } for (const props of arrayFrom(members.values())) { if (isArray(props)) { - const types = map(props, getTypeOfSymbol); - if (every(types, isLiteralType) && getIntersectionType(types).flags & TypeFlags.Never) { + if (every(props, hasLiteralLikeTypeAnnotation) && getIntersectionType(map(props, getTypeOfSymbol)).flags & TypeFlags.Never) { return true; } } @@ -12219,6 +12218,42 @@ namespace ts { return false; } + function hasLiteralLikeTypeAnnotation(prop: Symbol) { + if (prop.valueDeclaration) { + const node = getEffectiveTypeAnnotationNode(prop.valueDeclaration); + return !!node && isLiteralLikeType(node); + } + return false; + } + + function isLiteralLikeType(node: TypeNode): boolean { + switch (node.kind) { + case SyntaxKind.LiteralType: + return true; + case SyntaxKind.ParenthesizedType: + return isLiteralLikeType((node).type); + case SyntaxKind.UnionType: + return every((node).types, isLiteralLikeType); + case SyntaxKind.TypeReference: + return isReferenceToLiteralLikeType(node); + } + return false; + } + + function isReferenceToLiteralLikeType(node: TypeReferenceNode): boolean { + const symbol = resolveTypeReferenceName(node.typeName, SymbolFlags.Type); + if (symbol.flags & (SymbolFlags.Enum | SymbolFlags.EnumMember)) { + return true; + } + if (symbol.flags & SymbolFlags.TypeAlias) { + const declaration = find(symbol.declarations, isTypeAliasDeclaration); + if (declaration) { + return isLiteralLikeType(declaration.type); + } + } + return false; + } + function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) {