Skip to content

Commit cd7f039

Browse files
committed
Widening and non-widening computed enum types
1 parent 7f41c90 commit cd7f039

File tree

2 files changed

+38
-28
lines changed

2 files changed

+38
-28
lines changed

src/compiler/checker.ts

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ import {
157157
entityNameToString,
158158
EnumDeclaration,
159159
EnumMember,
160+
EnumType,
160161
equateValues,
161162
escapeLeadingUnderscores,
162163
escapeString,
@@ -9654,8 +9655,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
96549655
const t = types[i];
96559656
flags |= t.flags;
96569657
if (!(t.flags & TypeFlags.Nullable)) {
9657-
if (t.flags & (TypeFlags.BooleanLiteral | TypeFlags.EnumLiteral)) {
9658-
const baseType = t.flags & TypeFlags.BooleanLiteral ? booleanType : getBaseTypeOfEnumLiteralType(t as LiteralType);
9658+
if (t.flags & (TypeFlags.BooleanLiteral | TypeFlags.EnumLike)) {
9659+
const baseType = t.flags & TypeFlags.BooleanLiteral ? booleanType : getBaseTypeOfEnumLikeType(t as LiteralType);
96599660
if (baseType.flags & TypeFlags.Union) {
96609661
const count = (baseType as UnionType).types.length;
96619662
if (i + count <= types.length && getRegularTypeOfLiteralType(types[i + count - 1]) === getRegularTypeOfLiteralType((baseType as UnionType).types[count - 1])) {
@@ -11898,8 +11899,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1189811899
return links.declaredType;
1189911900
}
1190011901

11901-
function getBaseTypeOfEnumLiteralType(type: Type) {
11902-
return type.flags & TypeFlags.EnumLiteral && !(type.flags & TypeFlags.Union) ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)!) : type;
11902+
function getBaseTypeOfEnumLikeType(type: Type) {
11903+
return type.flags & TypeFlags.EnumLike && type.symbol.flags & SymbolFlags.EnumMember ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)!) : type;
1190311904
}
1190411905

1190511906
function getDeclaredTypeOfEnum(symbol: Symbol): Type {
@@ -11913,9 +11914,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1191311914
if (hasBindableName(member)) {
1191411915
const memberSymbol = getSymbolOfDeclaration(member);
1191511916
const value = getEnumMemberValue(member);
11916-
const memberType = value !== undefined ?
11917-
getFreshTypeOfLiteralType(getEnumLiteralType(value, getSymbolId(symbol), memberSymbol)) :
11918-
createTypeWithSymbol(TypeFlags.Enum, memberSymbol);
11917+
const memberType = getFreshTypeOfLiteralType(value !== undefined ?
11918+
getEnumLiteralType(value, getSymbolId(symbol), memberSymbol) :
11919+
createComputedEnumType(memberSymbol));
1191911920
getSymbolLinks(memberSymbol).declaredType = memberType;
1192011921
memberTypeList.push(getRegularTypeOfLiteralType(memberType));
1192111922
}
@@ -11925,7 +11926,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1192511926
}
1192611927
const enumType = memberTypeList.length ?
1192711928
getUnionType(memberTypeList, UnionReduction.Literal, symbol, /*aliasTypeArguments*/ undefined) :
11928-
createTypeWithSymbol(TypeFlags.Enum, symbol);
11929+
createComputedEnumType(symbol);
1192911930
if (enumType.flags & TypeFlags.Union) {
1193011931
enumType.flags |= TypeFlags.EnumLiteral;
1193111932
enumType.symbol = symbol;
@@ -11935,6 +11936,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1193511936
return links.declaredType;
1193611937
}
1193711938

11939+
function createComputedEnumType(symbol: Symbol) {
11940+
const regularType = createTypeWithSymbol(TypeFlags.Enum, symbol) as EnumType;
11941+
const freshType = createTypeWithSymbol(TypeFlags.Enum, symbol) as EnumType;
11942+
regularType.regularType = regularType;
11943+
regularType.freshType = freshType;
11944+
freshType.regularType = regularType;
11945+
freshType.freshType = freshType;
11946+
return regularType;
11947+
}
11948+
1193811949
function getDeclaredTypeOfEnumMember(symbol: Symbol): Type {
1193911950
const links = getSymbolLinks(symbol);
1194011951
if (!links.declaredType) {
@@ -16176,7 +16187,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1617616187
orderedRemoveItemAt(typeSet, 1);
1617716188
}
1617816189
}
16179-
if (includes & (TypeFlags.Literal | TypeFlags.UniqueESSymbol | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) || includes & TypeFlags.Void && includes & TypeFlags.Undefined) {
16190+
if (includes & (TypeFlags.Enum | TypeFlags.Literal | TypeFlags.UniqueESSymbol | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) || includes & TypeFlags.Void && includes & TypeFlags.Undefined) {
1618016191
removeRedundantLiteralTypes(typeSet, includes, !!(unionReduction & UnionReduction.Subtype));
1618116192
}
1618216193
if (includes & TypeFlags.StringLiteral && includes & TypeFlags.TemplateLiteral) {
@@ -18026,25 +18037,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1802618037
}
1802718038

1802818039
function getFreshTypeOfLiteralType(type: Type): Type {
18029-
if (type.flags & TypeFlags.Literal) {
18030-
if (!(type as LiteralType).freshType) {
18040+
if (type.flags & TypeFlags.Freshable) {
18041+
if (!(type as FreshableType).freshType) {
1803118042
const freshType = createLiteralType(type.flags, (type as LiteralType).value, (type as LiteralType).symbol, type as LiteralType);
1803218043
freshType.freshType = freshType;
18033-
(type as LiteralType).freshType = freshType;
18044+
(type as FreshableType).freshType = freshType;
1803418045
}
18035-
return (type as LiteralType).freshType;
18046+
return (type as FreshableType).freshType;
1803618047
}
1803718048
return type;
1803818049
}
1803918050

1804018051
function getRegularTypeOfLiteralType(type: Type): Type {
18041-
return type.flags & TypeFlags.Literal ? (type as LiteralType).regularType :
18052+
return type.flags & TypeFlags.Freshable ? (type as FreshableType).regularType :
1804218053
type.flags & TypeFlags.Union ? ((type as UnionType).regularType || ((type as UnionType).regularType = mapType(type, getRegularTypeOfLiteralType) as UnionType)) :
1804318054
type;
1804418055
}
1804518056

1804618057
function isFreshLiteralType(type: Type) {
18047-
return !!(type.flags & TypeFlags.Literal) && (type as LiteralType).freshType === type;
18058+
return !!(type.flags & TypeFlags.Freshable) && (type as LiteralType).freshType === type;
1804818059
}
1804918060

1805018061
function getStringLiteralType(value: string): StringLiteralType {
@@ -22935,7 +22946,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2293522946
}
2293622947

2293722948
function getBaseTypeOfLiteralType(type: Type): Type {
22938-
return type.flags & TypeFlags.EnumLiteral ? getBaseTypeOfEnumLiteralType(type as LiteralType) :
22949+
return type.flags & TypeFlags.EnumLike ? getBaseTypeOfEnumLikeType(type as LiteralType) :
2293922950
type.flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ? stringType :
2294022951
type.flags & TypeFlags.NumberLiteral ? numberType :
2294122952
type.flags & TypeFlags.BigIntLiteral ? bigintType :
@@ -22950,7 +22961,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2295022961
}
2295122962

2295222963
function getWidenedLiteralType(type: Type): Type {
22953-
return type.flags & TypeFlags.EnumLiteral && isFreshLiteralType(type) ? getBaseTypeOfEnumLiteralType(type as LiteralType) :
22964+
return type.flags & TypeFlags.EnumLike && isFreshLiteralType(type) ? getBaseTypeOfEnumLikeType(type as LiteralType) :
2295422965
type.flags & TypeFlags.StringLiteral && isFreshLiteralType(type) ? stringType :
2295522966
type.flags & TypeFlags.NumberLiteral && isFreshLiteralType(type) ? numberType :
2295622967
type.flags & TypeFlags.BigIntLiteral && isFreshLiteralType(type) ? bigintType :
@@ -25587,7 +25598,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2558725598
}
2558825599
return true;
2558925600
}
25590-
if (source.flags & TypeFlags.EnumLiteral && getBaseTypeOfEnumLiteralType(source as LiteralType) === target) {
25601+
if (source.flags & TypeFlags.EnumLike && getBaseTypeOfEnumLikeType(source as LiteralType) === target) {
2559125602
return true;
2559225603
}
2559325604
return containsType(target.types, source);

src/compiler/types.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6028,7 +6028,8 @@ export const enum TypeFlags {
60286028
/** @internal */
60296029
Nullable = Undefined | Null,
60306030
Literal = StringLiteral | NumberLiteral | BigIntLiteral | BooleanLiteral,
6031-
Unit = Literal | UniqueESSymbol | Nullable,
6031+
Unit = Enum | Literal | UniqueESSymbol | Nullable,
6032+
Freshable = Enum | Literal,
60326033
StringOrNumberLiteral = StringLiteral | NumberLiteral,
60336034
/** @internal */
60346035
StringOrNumberLiteralOrUnique = StringLiteral | NumberLiteral | UniqueESSymbol,
@@ -6122,22 +6123,20 @@ export interface NullableType extends IntrinsicType {
61226123
objectFlags: ObjectFlags;
61236124
}
61246125

6125-
/** @internal */
6126-
export interface FreshableIntrinsicType extends IntrinsicType {
6127-
freshType: IntrinsicType; // Fresh version of type
6128-
regularType: IntrinsicType; // Regular version of type
6126+
export interface FreshableType extends Type {
6127+
freshType: FreshableType; // Fresh version of type
6128+
regularType: FreshableType; // Regular version of type
61296129
}
61306130

61316131
/** @internal */
6132-
export type FreshableType = LiteralType | FreshableIntrinsicType;
6132+
export interface FreshableIntrinsicType extends FreshableType, IntrinsicType {
6133+
}
61336134

61346135
// String literal types (TypeFlags.StringLiteral)
61356136
// Numeric literal types (TypeFlags.NumberLiteral)
61366137
// BigInt literal types (TypeFlags.BigIntLiteral)
6137-
export interface LiteralType extends Type {
6138+
export interface LiteralType extends FreshableType {
61386139
value: string | number | PseudoBigInt; // Value of literal
6139-
freshType: LiteralType; // Fresh version of type
6140-
regularType: LiteralType; // Regular version of type
61416140
}
61426141

61436142
// Unique symbol types (TypeFlags.UniqueESSymbol)
@@ -6159,7 +6158,7 @@ export interface BigIntLiteralType extends LiteralType {
61596158
}
61606159

61616160
// Enum types (TypeFlags.Enum)
6162-
export interface EnumType extends Type {
6161+
export interface EnumType extends FreshableType {
61636162
}
61646163

61656164
// Types included in TypeFlags.ObjectFlagsType have an objectFlags property. Some ObjectFlags

0 commit comments

Comments
 (0)