Numeric and boolean literal types

This commit is contained in:
Anders Hejlsberg 2016-06-18 07:21:23 -07:00
parent c7dec0ea68
commit 89596cb73b
7 changed files with 170 additions and 115 deletions

View file

@ -114,6 +114,8 @@ namespace ts {
const stringType = createIntrinsicType(TypeFlags.String, "string");
const numberType = createIntrinsicType(TypeFlags.Number, "number");
const booleanType = createIntrinsicType(TypeFlags.Boolean, "boolean");
const trueType = createIntrinsicType(TypeFlags.BooleanLiteral, "true");
const falseType = createIntrinsicType(TypeFlags.BooleanLiteral, "false");
const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol");
const voidType = createIntrinsicType(TypeFlags.Void, "void");
const undefinedType = createIntrinsicType(TypeFlags.Undefined, "undefined");
@ -134,8 +136,8 @@ namespace ts {
const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);
@ -195,7 +197,8 @@ namespace ts {
const tupleTypes: Map<TupleType> = {};
const unionTypes: Map<UnionType> = {};
const intersectionTypes: Map<IntersectionType> = {};
const stringLiteralTypes: Map<StringLiteralType> = {};
const stringLiteralTypes: Map<LiteralType> = {};
const numericLiteralTypes: Map<LiteralType> = {};
const resolutionTargets: TypeSystemEntity[] = [];
const resolutionResults: boolean[] = [];
@ -2060,7 +2063,10 @@ namespace ts {
writeAnonymousType(<ObjectType>type, flags);
}
else if (type.flags & TypeFlags.StringLiteral) {
writer.writeStringLiteral(`"${escapeString((<StringLiteralType>type).text)}"`);
writer.writeStringLiteral(`"${escapeString((<LiteralType>type).text)}"`);
}
else if (type.flags & TypeFlags.NumberLiteral) {
writer.writeStringLiteral((<LiteralType>type).text);
}
else {
// Should never get here
@ -3718,7 +3724,7 @@ namespace ts {
case SyntaxKind.UndefinedKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.NeverKeyword:
case SyntaxKind.StringLiteralType:
case SyntaxKind.LiteralType:
return true;
case SyntaxKind.ArrayType:
return isIndependentType((<ArrayTypeNode>node).elementType);
@ -3863,7 +3869,7 @@ namespace ts {
}
function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], thisType: Type, parameters: Symbol[],
resolvedReturnType: Type, typePredicate: TypePredicate, minArgumentCount: number, hasRestParameter: boolean, hasStringLiterals: boolean): Signature {
resolvedReturnType: Type, typePredicate: TypePredicate, minArgumentCount: number, hasRestParameter: boolean, hasLiteralTypes: boolean): Signature {
const sig = new Signature(checker);
sig.declaration = declaration;
sig.typeParameters = typeParameters;
@ -3873,20 +3879,20 @@ namespace ts {
sig.typePredicate = typePredicate;
sig.minArgumentCount = minArgumentCount;
sig.hasRestParameter = hasRestParameter;
sig.hasStringLiterals = hasStringLiterals;
sig.hasLiteralTypes = hasLiteralTypes;
return sig;
}
function cloneSignature(sig: Signature): Signature {
return createSignature(sig.declaration, sig.typeParameters, sig.thisType, sig.parameters, sig.resolvedReturnType,
sig.typePredicate, sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals);
sig.typePredicate, sig.minArgumentCount, sig.hasRestParameter, sig.hasLiteralTypes);
}
function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {
const baseConstructorType = getBaseConstructorTypeOfClass(classType);
const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
if (baseSignatures.length === 0) {
return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false)];
}
const baseTypeNode = getBaseTypeNodeOfClass(classType);
const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode);
@ -4184,7 +4190,7 @@ namespace ts {
else if (type.flags & TypeFlags.NumberLike) {
type = globalNumberType;
}
else if (type.flags & TypeFlags.Boolean) {
else if (type.flags & TypeFlags.BooleanLike) {
type = globalBooleanType;
}
else if (type.flags & TypeFlags.ESSymbol) {
@ -4426,7 +4432,7 @@ namespace ts {
const links = getNodeLinks(declaration);
if (!links.resolvedSignature) {
const parameters: Symbol[] = [];
let hasStringLiterals = false;
let hasLiteralTypes = false;
let minArgumentCount = -1;
let thisType: Type = undefined;
let hasThisParameter: boolean;
@ -4452,8 +4458,8 @@ namespace ts {
parameters.push(paramSymbol);
}
if (param.type && param.type.kind === SyntaxKind.StringLiteralType) {
hasStringLiterals = true;
if (param.type && param.type.kind === SyntaxKind.LiteralType) {
hasLiteralTypes = true;
}
if (param.initializer || param.questionToken || param.dotDotDotToken) {
@ -4494,7 +4500,7 @@ namespace ts {
createTypePredicateFromTypePredicateNode(declaration.type as TypePredicateNode) :
undefined;
links.resolvedSignature = createSignature(declaration, typeParameters, thisType, parameters, returnType, typePredicate, minArgumentCount, hasRestParameter(declaration), hasStringLiterals);
links.resolvedSignature = createSignature(declaration, typeParameters, thisType, parameters, returnType, typePredicate, minArgumentCount, hasRestParameter(declaration), hasLiteralTypes);
}
return links.resolvedSignature;
}
@ -5182,19 +5188,53 @@ namespace ts {
return links.resolvedType;
}
function getStringLiteralTypeForText(text: string): StringLiteralType {
function getStringLiteralTypeForText(text: string): LiteralType {
if (hasProperty(stringLiteralTypes, text)) {
return stringLiteralTypes[text];
}
const type = stringLiteralTypes[text] = <StringLiteralType>createType(TypeFlags.StringLiteral);
const type = stringLiteralTypes[text] = <LiteralType>createType(TypeFlags.StringLiteral);
type.text = text;
return type;
}
function getTypeFromStringLiteralTypeNode(node: StringLiteralTypeNode): Type {
function createLiteralType(flags: TypeFlags, text: string) {
const type = <LiteralType>createType(flags);
type.text = text;
return type;
}
function getLiteralTypeForText(flags: TypeFlags, text: string) {
const map = flags & TypeFlags.StringLiteral ? stringLiteralTypes : numericLiteralTypes;
return hasProperty(map, text) ? map[text] : map[text] = createLiteralType(flags, text);
}
function getTypeFromLiteralExpression(node: Expression): Type {
switch (node.kind) {
case SyntaxKind.StringLiteral:
return getLiteralTypeForText(TypeFlags.StringLiteral, (<LiteralExpression>node).text);
case SyntaxKind.NumericLiteral:
return getLiteralTypeForText(TypeFlags.NumberLiteral, (<LiteralExpression>node).text);
case SyntaxKind.TrueKeyword:
return trueType;
case SyntaxKind.FalseKeyword:
return falseType;
case SyntaxKind.PrefixUnaryExpression:
if ((<PrefixUnaryExpression>node).operator === SyntaxKind.MinusToken &&
(<PrefixUnaryExpression>node).operand.kind === SyntaxKind.NumericLiteral) {
return getLiteralTypeForText(TypeFlags.NumberLiteral, "" + -(<LiteralExpression>(<PrefixUnaryExpression>node).operand).text);
}
}
return undefined;
}
function getTypeOfLiteralOrExpression(node: Expression): Type {
return getTypeFromLiteralExpression(node) || checkExpression(node);
}
function getTypeFromLiteralTypeNode(node: LiteralTypeNode): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
links.resolvedType = getStringLiteralTypeForText(unescapeIdentifier(node.text));
links.resolvedType = getTypeFromLiteralExpression(node.literal);
}
return links.resolvedType;
}
@ -5263,8 +5303,8 @@ namespace ts {
case SyntaxKind.ThisType:
case SyntaxKind.ThisKeyword:
return getTypeFromThisTypeNode(node);
case SyntaxKind.StringLiteralType:
return getTypeFromStringLiteralTypeNode(<StringLiteralTypeNode>node);
case SyntaxKind.LiteralType:
return getTypeFromLiteralTypeNode(<LiteralTypeNode>node);
case SyntaxKind.TypeReference:
case SyntaxKind.JSDocTypeReference:
return getTypeFromTypeReference(<TypeReferenceNode>node);
@ -5431,7 +5471,7 @@ namespace ts {
instantiateList(signature.parameters, mapper, instantiateSymbol),
instantiateType(signature.resolvedReturnType, mapper),
freshTypePredicate,
signature.minArgumentCount, signature.hasRestParameter, signature.hasStringLiterals);
signature.minArgumentCount, signature.hasRestParameter, signature.hasLiteralTypes);
result.target = signature;
result.mapper = mapper;
return result;
@ -5918,18 +5958,18 @@ namespace ts {
if (source.flags & TypeFlags.Null) {
if (!strictNullChecks || target.flags & TypeFlags.Null) return Ternary.True;
}
if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True;
if (source.flags & TypeFlags.NumberLike && target === numberType) return Ternary.True;
if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) {
if (result = enumRelatedTo(source, target, reportErrors)) {
return result;
}
}
if (source.flags & TypeFlags.StringLiteral && target === stringType) return Ternary.True;
if (source.flags & TypeFlags.StringLike && target === stringType) return Ternary.True;
if (relation === assignableRelation || relation === comparableRelation) {
if (source.flags & TypeFlags.Any) return Ternary.True;
if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True;
}
if (source.flags & TypeFlags.Boolean && target.flags & TypeFlags.Boolean) {
if (source.flags & TypeFlags.BooleanLike && target.flags & TypeFlags.Boolean) {
return Ternary.True;
}
}
@ -6834,9 +6874,9 @@ namespace ts {
return !!getPropertyOfType(type, "0");
}
function isStringLiteralUnionType(type: Type): boolean {
return type.flags & TypeFlags.StringLiteral ? true :
type.flags & TypeFlags.Union ? forEach((<UnionType>type).types, isStringLiteralUnionType) :
function isLiteralUnionType(type: Type): boolean {
return type.flags & TypeFlags.Literal ? true :
type.flags & TypeFlags.Union ? forEach((<UnionType>type).types, isLiteralUnionType) :
false;
}
@ -7528,7 +7568,7 @@ namespace ts {
if (flags & TypeFlags.NumberLike) {
return strictNullChecks ? TypeFacts.NumberStrictFacts : TypeFacts.NumberFacts;
}
if (flags & TypeFlags.Boolean) {
if (flags & TypeFlags.BooleanLike) {
return strictNullChecks ? TypeFacts.BooleanStrictFacts : TypeFacts.BooleanFacts;
}
if (flags & TypeFlags.ObjectType) {
@ -7703,11 +7743,7 @@ namespace ts {
}
function getTypeOfSwitchClause(clause: CaseClause | DefaultClause) {
if (clause.kind === SyntaxKind.CaseClause) {
const expr = (<CaseClause>clause).expression;
return expr.kind === SyntaxKind.StringLiteral ? getStringLiteralTypeForText((<StringLiteral>expr).text) : checkExpression(expr);
}
return undefined;
return clause.kind === SyntaxKind.CaseClause ? getTypeOfLiteralOrExpression((<CaseClause>clause).expression) : undefined;
}
function getSwitchClauseTypes(switchStatement: SwitchStatement): Type[] {
@ -8021,11 +8057,11 @@ namespace ts {
}
const propName = propAccess.name.text;
const propType = getTypeOfPropertyOfType(type, propName);
if (!propType || !isStringLiteralUnionType(propType)) {
if (!propType || !isLiteralUnionType(propType)) {
return type;
}
const discriminantType = value.kind === SyntaxKind.StringLiteral ? getStringLiteralTypeForText((<StringLiteral>value).text) : checkExpression(value);
if (!isStringLiteralUnionType(discriminantType)) {
const discriminantType = getTypeOfLiteralOrExpression(value);
if (!isLiteralUnionType(discriminantType)) {
return type;
}
if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
@ -8047,7 +8083,7 @@ namespace ts {
}
const propName = (<PropertyAccessExpression>switchStatement.expression).name.text;
const propType = getTypeOfPropertyOfType(type, propName);
if (!propType || !isStringLiteralUnionType(propType)) {
if (!propType || !isLiteralUnionType(propType)) {
return type;
}
const switchTypes = getSwitchClauseTypes(switchStatement);
@ -10446,7 +10482,7 @@ namespace ts {
// specialized signatures always need to be placed before non-specialized signatures regardless
// of the cutoff position; see GH#1133
if (signature.hasStringLiterals) {
if (signature.hasLiteralTypes) {
specializedIndex++;
spliceIndex = specializedIndex;
// The cutoff index always needs to be greater than or equal to the specialized signature index
@ -10705,7 +10741,7 @@ namespace ts {
// for the argument. In that case, we should check the argument.
if (argType === undefined) {
argType = arg.kind === SyntaxKind.StringLiteral && !reportErrors
? getStringLiteralTypeForText((<StringLiteral>arg).text)
? getTypeFromLiteralExpression(arg)
: checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
}
@ -11877,7 +11913,7 @@ namespace ts {
}
const propName = (<PropertyAccessExpression>expr).name.text;
const propType = getTypeOfPropertyOfType(type, propName);
if (!propType || !isStringLiteralUnionType(propType)) {
if (!propType || !isLiteralUnionType(propType)) {
return false;
}
const switchTypes = getSwitchClauseTypes(node);
@ -12217,6 +12253,9 @@ namespace ts {
function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type {
const operandType = checkExpression(node.operand);
if (node.operator === SyntaxKind.MinusToken && node.operand.kind === SyntaxKind.NumericLiteral && hasLiteralContextualType(node)) {
return getTypeFromLiteralExpression(node);
}
switch (node.operator) {
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToken:
@ -12520,8 +12559,8 @@ namespace ts {
let suggestedOperator: SyntaxKind;
// if a user tries to apply a bitwise operator to 2 boolean operands
// try and return them a helpful suggestion
if ((leftType.flags & TypeFlags.Boolean) &&
(rightType.flags & TypeFlags.Boolean) &&
if ((leftType.flags & TypeFlags.BooleanLike) &&
(rightType.flags & TypeFlags.BooleanLike) &&
(suggestedOperator = getSuggestedBooleanOperator(operatorToken.kind)) !== undefined) {
error(errorNode || operatorToken, Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, tokenToString(operatorToken.kind), tokenToString(suggestedOperator));
}
@ -12734,13 +12773,18 @@ namespace ts {
return getUnionType([type1, type2]);
}
function checkStringLiteralExpression(node: StringLiteral): Type {
const contextualType = getContextualType(node);
if (contextualType && isStringLiteralUnionType(contextualType)) {
return getStringLiteralTypeForText(node.text);
}
function hasLiteralContextualType(node: Expression) {
return isLiteralUnionType(getContextualType(node) || unknownType);
}
return stringType;
function checkLiteralExpression(node: Expression): Type {
const type = node.kind === SyntaxKind.StringLiteral ? stringType :
node.kind === SyntaxKind.TrueKeyword || node.kind === SyntaxKind.FalseKeyword ? booleanType :
numberType;
if (type === numberType) {
checkGrammarNumericLiteral(<LiteralExpression>node);
}
return hasLiteralContextualType(node) ? getTypeFromLiteralExpression(node) : type;
}
function checkTemplateExpression(node: TemplateExpression): Type {
@ -12855,12 +12899,6 @@ namespace ts {
return type;
}
function checkNumericLiteral(node: LiteralExpression): Type {
// Grammar checking
checkGrammarNumericLiteral(node);
return numberType;
}
function checkExpressionWorker(node: Expression, contextualMapper: TypeMapper): Type {
switch (node.kind) {
case SyntaxKind.Identifier:
@ -12871,15 +12909,13 @@ namespace ts {
return checkSuperExpression(node);
case SyntaxKind.NullKeyword:
return nullWideningType;
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
return booleanType;
case SyntaxKind.NumericLiteral:
return checkNumericLiteral(<LiteralExpression>node);
return checkLiteralExpression(node);
case SyntaxKind.TemplateExpression:
return checkTemplateExpression(<TemplateExpression>node);
case SyntaxKind.StringLiteral:
return checkStringLiteralExpression(<StringLiteral>node);
case SyntaxKind.NoSubstitutionTemplateLiteral:
return stringType;
case SyntaxKind.RegularExpressionLiteral:
@ -17605,7 +17641,7 @@ namespace ts {
else if (isTypeOfKind(type, TypeFlags.Void)) {
return TypeReferenceSerializationKind.VoidType;
}
else if (isTypeOfKind(type, TypeFlags.Boolean)) {
else if (isTypeOfKind(type, TypeFlags.BooleanLike)) {
return TypeReferenceSerializationKind.BooleanType;
}
else if (isTypeOfKind(type, TypeFlags.NumberLike)) {

View file

@ -397,7 +397,7 @@ namespace ts {
case SyntaxKind.NullKeyword:
case SyntaxKind.NeverKeyword:
case SyntaxKind.ThisType:
case SyntaxKind.StringLiteralType:
case SyntaxKind.LiteralType:
return writeTextOfNode(currentText, type);
case SyntaxKind.ExpressionWithTypeArguments:
return emitExpressionWithTypeArguments(<ExpressionWithTypeArguments>type);

View file

@ -6009,7 +6009,7 @@ const _super = (function (geti, seti) {
return;
case SyntaxKind.StringKeyword:
case SyntaxKind.StringLiteralType:
case SyntaxKind.LiteralType:
write("String");
return;

View file

@ -128,6 +128,8 @@ namespace ts {
return visitNodes(cbNodes, (<UnionOrIntersectionTypeNode>node).types);
case SyntaxKind.ParenthesizedType:
return visitNode(cbNode, (<ParenthesizedTypeNode>node).type);
case SyntaxKind.LiteralType:
return visitNode(cbNode, (<LiteralTypeNode>node).literal);
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
return visitNodes(cbNodes, (<BindingPattern>node).elements);
@ -1918,10 +1920,6 @@ namespace ts {
return finishNode(span);
}
function parseStringLiteralTypeNode(): StringLiteralTypeNode {
return <StringLiteralTypeNode>parseLiteralLikeNode(SyntaxKind.StringLiteralType, /*internName*/ true);
}
function parseLiteralNode(internName?: boolean): LiteralExpression {
return <LiteralExpression>parseLiteralLikeNode(token, internName);
}
@ -2387,6 +2385,17 @@ namespace ts {
return token === SyntaxKind.DotToken ? undefined : node;
}
function parseLiteralTypeNode(): LiteralTypeNode {
const node = <LiteralTypeNode>createNode(SyntaxKind.LiteralType);
node.literal = parseSimpleUnaryExpression();
finishNode(node);
return node;
}
function nextTokenIsNumericLiteral() {
return nextToken() === SyntaxKind.NumericLiteral;
}
function parseNonArrayType(): TypeNode {
switch (token) {
case SyntaxKind.AnyKeyword:
@ -2400,7 +2409,12 @@ namespace ts {
const node = tryParse(parseKeywordAndNoDot);
return node || parseTypeReference();
case SyntaxKind.StringLiteral:
return parseStringLiteralTypeNode();
case SyntaxKind.NumericLiteral:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
return parseLiteralTypeNode();
case SyntaxKind.MinusToken:
return lookAhead(nextTokenIsNumericLiteral) ? parseLiteralTypeNode() : parseTypeReference();
case SyntaxKind.VoidKeyword:
case SyntaxKind.NullKeyword:
return parseTokenNode<TypeNode>();
@ -2444,7 +2458,12 @@ namespace ts {
case SyntaxKind.LessThanToken:
case SyntaxKind.NewKeyword:
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
return true;
case SyntaxKind.MinusToken:
return lookAhead(nextTokenIsNumericLiteral);
case SyntaxKind.OpenParenToken:
// Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier,
// or something that starts a type. We don't want to consider things like '(1)' a type.

View file

@ -210,7 +210,7 @@ namespace ts {
IntersectionType,
ParenthesizedType,
ThisType,
StringLiteralType,
LiteralType,
// Binding patterns
ObjectBindingPattern,
ArrayBindingPattern,
@ -361,7 +361,7 @@ namespace ts {
FirstFutureReservedWord = ImplementsKeyword,
LastFutureReservedWord = YieldKeyword,
FirstTypeNode = TypePredicate,
LastTypeNode = StringLiteralType,
LastTypeNode = LiteralType,
FirstPunctuation = OpenBraceToken,
LastPunctuation = CaretEqualsToken,
FirstToken = Unknown,
@ -790,8 +790,9 @@ namespace ts {
}
// @kind(SyntaxKind.StringLiteralType)
export interface StringLiteralTypeNode extends LiteralLikeNode, TypeNode {
export interface LiteralTypeNode extends TypeNode {
_stringLiteralTypeBrand: any;
literal: Expression;
}
// @kind(SyntaxKind.StringLiteral)
@ -2197,50 +2198,54 @@ namespace ts {
}
export const enum TypeFlags {
Any = 0x00000001,
String = 0x00000002,
Number = 0x00000004,
Boolean = 0x00000008,
Void = 0x00000010,
Undefined = 0x00000020,
Null = 0x00000040,
Enum = 0x00000080, // Enum type
StringLiteral = 0x00000100, // String literal type
TypeParameter = 0x00000200, // Type parameter
Class = 0x00000400, // Class
Interface = 0x00000800, // Interface
Reference = 0x00001000, // Generic type reference
Tuple = 0x00002000, // Tuple
Union = 0x00004000, // Union (T | U)
Intersection = 0x00008000, // Intersection (T & U)
Anonymous = 0x00010000, // Anonymous
Instantiated = 0x00020000, // Instantiated anonymous type
Any = 1 << 0,
String = 1 << 1,
Number = 1 << 2,
Boolean = 1 << 3,
StringLiteral = 1 << 4, // String literal type
NumberLiteral = 1 << 5,
BooleanLiteral = 1 << 6,
ESSymbol = 1 << 7, // Type of symbol primitive introduced in ES6
Void = 1 << 8,
Undefined = 1 << 9,
Null = 1 << 10,
Never = 1 << 11, // Never type
Enum = 1 << 12, // Enum type
TypeParameter = 1 << 13, // Type parameter
Class = 1 << 14, // Class
Interface = 1 << 15, // Interface
Reference = 1 << 16, // Generic type reference
Tuple = 1 << 17, // Tuple
Union = 1 << 18, // Union (T | U)
Intersection = 1 << 19, // Intersection (T & U)
Anonymous = 1 << 20, // Anonymous
Instantiated = 1 << 21, // Instantiated anonymous type
/* @internal */
FromSignature = 0x00040000, // Created for signature assignment check
ObjectLiteral = 0x00080000, // Originates in an object literal
FromSignature = 1 << 22, // Created for signature assignment check
ObjectLiteral = 1 << 23, // Originates in an object literal
/* @internal */
FreshObjectLiteral = 0x00100000, // Fresh object literal type
FreshObjectLiteral = 1 << 24, // Fresh object literal type
/* @internal */
ContainsWideningType = 0x00200000, // Type is or contains undefined or null widening type
ContainsWideningType = 1 << 25, // Type is or contains undefined or null widening type
/* @internal */
ContainsObjectLiteral = 0x00400000, // Type is or contains object literal type
ContainsObjectLiteral = 1 << 26, // Type is or contains object literal type
/* @internal */
ContainsAnyFunctionType = 0x00800000, // Type is or contains object literal type
ESSymbol = 0x01000000, // Type of symbol primitive introduced in ES6
ThisType = 0x02000000, // This type
ObjectLiteralPatternWithComputedProperties = 0x04000000, // Object literal type implied by binding pattern has computed properties
Never = 0x08000000, // Never type
ContainsAnyFunctionType = 1 << 27, // Type is or contains object literal type
ThisType = 1 << 28, // This type
ObjectLiteralPatternWithComputedProperties = 1 << 29, // Object literal type implied by binding pattern has computed properties
/* @internal */
Nullable = Undefined | Null,
Literal = StringLiteral | NumberLiteral | BooleanLiteral,
/* @internal */
Falsy = Void | Undefined | Null, // TODO: Add false, 0, and ""
/* @internal */
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null | Never,
Intrinsic = Any | String | Number | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never,
/* @internal */
Primitive = String | Number | Boolean | ESSymbol | Void | Undefined | Null | StringLiteral | Enum,
StringLike = String | StringLiteral,
NumberLike = Number | Enum,
NumberLike = Number | NumberLiteral | Enum,
BooleanLike = Boolean | BooleanLiteral,
ObjectType = Class | Interface | Reference | Tuple | Anonymous,
UnionOrIntersection = Union | Intersection,
StructuredType = ObjectType | Union | Intersection,
@ -2271,7 +2276,7 @@ namespace ts {
}
// String literal types (TypeFlags.StringLiteral)
export interface StringLiteralType extends Type {
export interface LiteralType extends Type {
text: string; // Text of string literal
}
@ -2394,7 +2399,7 @@ namespace ts {
/* @internal */
hasRestParameter: boolean; // True if last parameter is rest parameter
/* @internal */
hasStringLiterals: boolean; // True if specialized
hasLiteralTypes: boolean; // True if specialized
/* @internal */
target?: Signature; // Instantiation target
/* @internal */

View file

@ -783,7 +783,7 @@ namespace ts {
resolvedReturnType: Type;
minArgumentCount: number;
hasRestParameter: boolean;
hasStringLiterals: boolean;
hasLiteralTypes: boolean;
// Undefined is used to indicate the value has not been computed. If, after computing, the
// symbol has no doc comment, then the empty string will be returned.
@ -3633,7 +3633,6 @@ namespace ts {
function isInStringOrRegularExpressionOrTemplateLiteral(contextToken: Node): boolean {
if (contextToken.kind === SyntaxKind.StringLiteral
|| contextToken.kind === SyntaxKind.StringLiteralType
|| contextToken.kind === SyntaxKind.RegularExpressionLiteral
|| isTemplateLiteralKind(contextToken.kind)) {
const start = contextToken.getStart();
@ -4298,7 +4297,7 @@ namespace ts {
else {
if (type.flags & TypeFlags.StringLiteral) {
result.push({
name: (<StringLiteralType>type).text,
name: (<LiteralType>type).text,
kindModifiers: ScriptElementKindModifier.none,
kind: ScriptElementKind.variableElement,
sortText: "0"
@ -6985,7 +6984,6 @@ namespace ts {
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.QualifiedName:
case SyntaxKind.StringLiteral:
case SyntaxKind.StringLiteralType:
case SyntaxKind.FalseKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.NullKeyword:
@ -7489,7 +7487,7 @@ namespace ts {
else if (tokenKind === SyntaxKind.NumericLiteral) {
return ClassificationType.numericLiteral;
}
else if (tokenKind === SyntaxKind.StringLiteral || tokenKind === SyntaxKind.StringLiteralType) {
else if (tokenKind === SyntaxKind.StringLiteral) {
return token.parent.kind === SyntaxKind.JsxAttribute ? ClassificationType.jsxAttributeStringLiteralValue : ClassificationType.stringLiteral;
}
else if (tokenKind === SyntaxKind.RegularExpressionLiteral) {
@ -7983,11 +7981,11 @@ namespace ts {
}
}
function getStringLiteralTypeForNode(node: StringLiteral | StringLiteralTypeNode, typeChecker: TypeChecker): StringLiteralType {
const searchNode = node.parent.kind === SyntaxKind.StringLiteralType ? <StringLiteralTypeNode>node.parent : node;
function getStringLiteralTypeForNode(node: StringLiteral | LiteralTypeNode, typeChecker: TypeChecker): LiteralType {
const searchNode = node.parent.kind === SyntaxKind.LiteralType ? <LiteralTypeNode>node.parent : node;
const type = typeChecker.getTypeAtLocation(searchNode);
if (type && type.flags & TypeFlags.StringLiteral) {
return <StringLiteralType>type;
return <LiteralType>type;
}
return undefined;
}
@ -8474,7 +8472,7 @@ namespace ts {
addResult(start, end, classFromKind(token));
if (end >= text.length) {
if (token === SyntaxKind.StringLiteral || token === SyntaxKind.StringLiteralType) {
if (token === SyntaxKind.StringLiteral) {
// Check to see if we finished up on a multiline string literal.
const tokenText = scanner.getTokenText();
if (scanner.isUnterminated()) {
@ -8624,7 +8622,6 @@ namespace ts {
case SyntaxKind.NumericLiteral:
return ClassificationType.numericLiteral;
case SyntaxKind.StringLiteral:
case SyntaxKind.StringLiteralType:
return ClassificationType.stringLiteral;
case SyntaxKind.RegularExpressionLiteral:
return ClassificationType.regularExpressionLiteral;

View file

@ -428,8 +428,7 @@ namespace ts {
export function isInString(sourceFile: SourceFile, position: number): boolean {
const previousToken = findPrecedingToken(position, sourceFile);
if (previousToken &&
(previousToken.kind === SyntaxKind.StringLiteral || previousToken.kind === SyntaxKind.StringLiteralType)) {
if (previousToken && previousToken.kind === SyntaxKind.StringLiteral) {
const start = previousToken.getStart();
const end = previousToken.getEnd();
@ -627,7 +626,6 @@ namespace ts {
export function isStringOrRegularExpressionOrTemplateLiteral(kind: SyntaxKind): boolean {
if (kind === SyntaxKind.StringLiteral
|| kind === SyntaxKind.StringLiteralType
|| kind === SyntaxKind.RegularExpressionLiteral
|| isTemplateLiteralKind(kind)) {
return true;