Numeric and boolean literal types
This commit is contained in:
parent
c7dec0ea68
commit
89596cb73b
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -6009,7 +6009,7 @@ const _super = (function (geti, seti) {
|
|||
return;
|
||||
|
||||
case SyntaxKind.StringKeyword:
|
||||
case SyntaxKind.StringLiteralType:
|
||||
case SyntaxKind.LiteralType:
|
||||
write("String");
|
||||
return;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue