mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
Introduce boolean literal freshness (#27042)
This commit is contained in:
parent
4eb59a2d77
commit
20eafb5b74
@ -296,8 +296,8 @@ namespace ts {
|
||||
createPromiseType,
|
||||
createArrayType,
|
||||
getBooleanType: () => booleanType,
|
||||
getFalseType: () => falseType,
|
||||
getTrueType: () => trueType,
|
||||
getFalseType: (fresh?) => fresh ? falseType : regularFalseType,
|
||||
getTrueType: (fresh?) => fresh ? trueType : regularTrueType,
|
||||
getVoidType: () => voidType,
|
||||
getUndefinedType: () => undefinedType,
|
||||
getNullType: () => nullType,
|
||||
@ -405,9 +405,22 @@ namespace ts {
|
||||
const nullWideningType = strictNullChecks ? nullType : createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsWideningType, "null");
|
||||
const stringType = createIntrinsicType(TypeFlags.String, "string");
|
||||
const numberType = createIntrinsicType(TypeFlags.Number, "number");
|
||||
const falseType = createIntrinsicType(TypeFlags.BooleanLiteral, "false");
|
||||
const trueType = createIntrinsicType(TypeFlags.BooleanLiteral, "true");
|
||||
const booleanType = createBooleanType([falseType, trueType]);
|
||||
const falseType = createIntrinsicType(TypeFlags.BooleanLiteral, "false") as FreshableIntrinsicType;
|
||||
const regularFalseType = createIntrinsicType(TypeFlags.BooleanLiteral, "false") as FreshableIntrinsicType;
|
||||
const trueType = createIntrinsicType(TypeFlags.BooleanLiteral, "true") as FreshableIntrinsicType;
|
||||
const regularTrueType = createIntrinsicType(TypeFlags.BooleanLiteral, "true") as FreshableIntrinsicType;
|
||||
falseType.flags |= TypeFlags.FreshLiteral;
|
||||
trueType.flags |= TypeFlags.FreshLiteral;
|
||||
trueType.regularType = regularTrueType;
|
||||
regularTrueType.freshType = trueType;
|
||||
falseType.regularType = regularFalseType;
|
||||
regularFalseType.freshType = falseType;
|
||||
const booleanType = createBooleanType([regularFalseType, regularTrueType]);
|
||||
// Also mark all combinations of fresh/regular booleans as "Boolean" so they print as `boolean` instead of `true | false`
|
||||
// (The union is cached, so simply doing the marking here is sufficient)
|
||||
createBooleanType([regularFalseType, trueType]);
|
||||
createBooleanType([falseType, regularTrueType]);
|
||||
createBooleanType([falseType, trueType]);
|
||||
const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol");
|
||||
const voidType = createIntrinsicType(TypeFlags.Void, "void");
|
||||
const neverType = createIntrinsicType(TypeFlags.Never, "never");
|
||||
@ -4173,7 +4186,7 @@ namespace ts {
|
||||
const baseType = t.flags & TypeFlags.BooleanLiteral ? booleanType : getBaseTypeOfEnumLiteralType(<LiteralType>t);
|
||||
if (baseType.flags & TypeFlags.Union) {
|
||||
const count = (<UnionType>baseType).types.length;
|
||||
if (i + count <= types.length && types[i + count - 1] === (<UnionType>baseType).types[count - 1]) {
|
||||
if (i + count <= types.length && getRegularTypeOfLiteralType(types[i + count - 1]) === getRegularTypeOfLiteralType((<UnionType>baseType).types[count - 1])) {
|
||||
result.push(baseType);
|
||||
i += count - 1;
|
||||
continue;
|
||||
@ -6160,7 +6173,7 @@ namespace ts {
|
||||
if (type.flags & TypeFlags.UniqueESSymbol) {
|
||||
return `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as __String;
|
||||
}
|
||||
if (type.flags & TypeFlags.StringOrNumberLiteral) {
|
||||
if (type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) {
|
||||
return escapeLeadingUnderscores("" + (<LiteralType>type).value);
|
||||
}
|
||||
return Debug.fail();
|
||||
@ -8813,7 +8826,7 @@ namespace ts {
|
||||
t.flags & TypeFlags.StringLiteral && includes & TypeFlags.String ||
|
||||
t.flags & TypeFlags.NumberLiteral && includes & TypeFlags.Number ||
|
||||
t.flags & TypeFlags.UniqueESSymbol && includes & TypeFlags.ESSymbol ||
|
||||
t.flags & TypeFlags.StringOrNumberLiteral && t.flags & TypeFlags.FreshLiteral && containsType(types, (<LiteralType>t).regularType);
|
||||
t.flags & TypeFlags.Literal && t.flags & TypeFlags.FreshLiteral && containsType(types, (<LiteralType>t).regularType);
|
||||
if (remove) {
|
||||
orderedRemoveItemAt(types, i);
|
||||
}
|
||||
@ -9813,8 +9826,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getFreshTypeOfLiteralType(type: Type): Type {
|
||||
if (type.flags & TypeFlags.StringOrNumberLiteral && !(type.flags & TypeFlags.FreshLiteral)) {
|
||||
if (!(<LiteralType>type).freshType) {
|
||||
if (type.flags & TypeFlags.Literal && !(type.flags & TypeFlags.FreshLiteral)) {
|
||||
if (!(<LiteralType>type).freshType) { // NOTE: Safe because all freshable intrinsics always have fresh types already
|
||||
const freshType = createLiteralType(type.flags | TypeFlags.FreshLiteral, (<LiteralType>type).value, (<LiteralType>type).symbol);
|
||||
freshType.regularType = <LiteralType>type;
|
||||
(<LiteralType>type).freshType = freshType;
|
||||
@ -9825,7 +9838,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getRegularTypeOfLiteralType(type: Type): Type {
|
||||
return type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral ? (<LiteralType>type).regularType :
|
||||
return type.flags & TypeFlags.Literal && type.flags & TypeFlags.FreshLiteral ? (<LiteralType>type).regularType :
|
||||
type.flags & TypeFlags.Union ? getUnionType(sameMap((<UnionType>type).types, getRegularTypeOfLiteralType)) :
|
||||
type;
|
||||
}
|
||||
@ -11038,11 +11051,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isTypeRelatedTo(source: Type, target: Type, relation: Map<RelationComparisonResult>) {
|
||||
if (source.flags & TypeFlags.StringOrNumberLiteral && source.flags & TypeFlags.FreshLiteral) {
|
||||
source = (<LiteralType>source).regularType;
|
||||
if (source.flags & TypeFlags.Literal && source.flags & TypeFlags.FreshLiteral) {
|
||||
source = (<FreshableType>source).regularType;
|
||||
}
|
||||
if (target.flags & TypeFlags.StringOrNumberLiteral && target.flags & TypeFlags.FreshLiteral) {
|
||||
target = (<LiteralType>target).regularType;
|
||||
if (target.flags & TypeFlags.Literal && target.flags & TypeFlags.FreshLiteral) {
|
||||
target = (<FreshableType>target).regularType;
|
||||
}
|
||||
if (source === target ||
|
||||
relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) ||
|
||||
@ -11197,11 +11210,11 @@ namespace ts {
|
||||
* * Ternary.False if they are not related.
|
||||
*/
|
||||
function isRelatedTo(source: Type, target: Type, reportErrors = false, headMessage?: DiagnosticMessage): Ternary {
|
||||
if (source.flags & TypeFlags.StringOrNumberLiteral && source.flags & TypeFlags.FreshLiteral) {
|
||||
source = (<LiteralType>source).regularType;
|
||||
if (source.flags & TypeFlags.Literal && source.flags & TypeFlags.FreshLiteral) {
|
||||
source = (<FreshableType>source).regularType;
|
||||
}
|
||||
if (target.flags & TypeFlags.StringOrNumberLiteral && target.flags & TypeFlags.FreshLiteral) {
|
||||
target = (<LiteralType>target).regularType;
|
||||
if (target.flags & TypeFlags.Literal && target.flags & TypeFlags.FreshLiteral) {
|
||||
target = (<FreshableType>target).regularType;
|
||||
}
|
||||
if (source.flags & TypeFlags.Substitution) {
|
||||
source = relation === definitelyAssignableRelation ? (<SubstitutionType>source).typeVariable : (<SubstitutionType>source).substitute;
|
||||
@ -12769,7 +12782,7 @@ namespace ts {
|
||||
return type.flags & TypeFlags.EnumLiteral && type.flags & TypeFlags.FreshLiteral ? getBaseTypeOfEnumLiteralType(<LiteralType>type) :
|
||||
type.flags & TypeFlags.StringLiteral && type.flags & TypeFlags.FreshLiteral ? stringType :
|
||||
type.flags & TypeFlags.NumberLiteral && type.flags & TypeFlags.FreshLiteral ? numberType :
|
||||
type.flags & TypeFlags.BooleanLiteral ? booleanType :
|
||||
type.flags & TypeFlags.BooleanLiteral && type.flags & TypeFlags.FreshLiteral ? booleanType :
|
||||
type.flags & TypeFlags.Union ? getUnionType(sameMap((<UnionType>type).types, getWidenedLiteralType)) :
|
||||
type;
|
||||
}
|
||||
@ -12823,7 +12836,7 @@ namespace ts {
|
||||
return type.flags & TypeFlags.Union ? getFalsyFlagsOfTypes((<UnionType>type).types) :
|
||||
type.flags & TypeFlags.StringLiteral ? (<LiteralType>type).value === "" ? TypeFlags.StringLiteral : 0 :
|
||||
type.flags & TypeFlags.NumberLiteral ? (<LiteralType>type).value === 0 ? TypeFlags.NumberLiteral : 0 :
|
||||
type.flags & TypeFlags.BooleanLiteral ? type === falseType ? TypeFlags.BooleanLiteral : 0 :
|
||||
type.flags & TypeFlags.BooleanLiteral ? (type === falseType || type === regularFalseType) ? TypeFlags.BooleanLiteral : 0 :
|
||||
type.flags & TypeFlags.PossiblyFalsy;
|
||||
}
|
||||
|
||||
@ -12840,7 +12853,8 @@ namespace ts {
|
||||
function getDefinitelyFalsyPartOfType(type: Type): Type {
|
||||
return type.flags & TypeFlags.String ? emptyStringType :
|
||||
type.flags & TypeFlags.Number ? zeroType :
|
||||
type.flags & TypeFlags.Boolean || type === falseType ? falseType :
|
||||
type.flags & TypeFlags.Boolean || type === regularFalseType ? regularFalseType :
|
||||
type === falseType ? falseType :
|
||||
type.flags & (TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null) ||
|
||||
type.flags & TypeFlags.StringLiteral && (<LiteralType>type).value === "" ||
|
||||
type.flags & TypeFlags.NumberLiteral && (<LiteralType>type).value === 0 ? type :
|
||||
@ -14095,7 +14109,10 @@ namespace ts {
|
||||
if (assignedType.flags & TypeFlags.Never) {
|
||||
return assignedType;
|
||||
}
|
||||
const reducedType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t));
|
||||
let reducedType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t));
|
||||
if (assignedType.flags & (TypeFlags.FreshLiteral | TypeFlags.Literal)) {
|
||||
reducedType = mapType(reducedType, getFreshTypeOfLiteralType); // Ensure that if the assignment is a fresh type, that we narrow to fresh types
|
||||
}
|
||||
// Our crude heuristic produces an invalid result in some cases: see GH#26130.
|
||||
// For now, when that happens, we give up and don't narrow at all. (This also
|
||||
// means we'll never narrow for erroneous assignments where the assigned type
|
||||
@ -14148,8 +14165,8 @@ namespace ts {
|
||||
}
|
||||
if (flags & TypeFlags.BooleanLike) {
|
||||
return strictNullChecks ?
|
||||
type === falseType ? TypeFacts.FalseStrictFacts : TypeFacts.TrueStrictFacts :
|
||||
type === falseType ? TypeFacts.FalseFacts : TypeFacts.TrueFacts;
|
||||
(type === falseType || type === regularFalseType) ? TypeFacts.FalseStrictFacts : TypeFacts.TrueStrictFacts :
|
||||
(type === falseType || type === regularFalseType) ? TypeFacts.FalseFacts : TypeFacts.TrueFacts;
|
||||
}
|
||||
if (flags & TypeFlags.Object) {
|
||||
return isFunctionObjectType(<ObjectType>type) ?
|
||||
@ -28381,19 +28398,20 @@ namespace ts {
|
||||
function isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean {
|
||||
if (isDeclarationReadonly(node) || isVariableDeclaration(node) && isVarConst(node)) {
|
||||
const type = getTypeOfSymbol(getSymbolOfNode(node));
|
||||
return !!(type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral);
|
||||
return !!(type.flags & TypeFlags.Literal && type.flags & TypeFlags.FreshLiteral);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function literalTypeToNode(type: LiteralType, enclosing: Node): Expression {
|
||||
const enumResult = type.flags & TypeFlags.EnumLiteral && nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing);
|
||||
return enumResult || createLiteral(type.value);
|
||||
function literalTypeToNode(type: FreshableType, enclosing: Node): Expression {
|
||||
const enumResult = type.flags & TypeFlags.EnumLiteral ? nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing)
|
||||
: type === trueType ? createTrue() : type === falseType && createFalse();
|
||||
return enumResult || createLiteral((type as LiteralType).value);
|
||||
}
|
||||
|
||||
function createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration) {
|
||||
const type = getTypeOfSymbol(getSymbolOfNode(node));
|
||||
return literalTypeToNode(<LiteralType>type, node);
|
||||
return literalTypeToNode(<FreshableType>type, node);
|
||||
}
|
||||
|
||||
function createResolver(): EmitResolver {
|
||||
@ -29765,7 +29783,7 @@ namespace ts {
|
||||
|
||||
function checkAmbientInitializer(node: VariableDeclaration | PropertyDeclaration | PropertySignature) {
|
||||
if (node.initializer) {
|
||||
const isInvalidInitializer = !(isStringOrNumberLiteralExpression(node.initializer) || isSimpleLiteralEnumReference(node.initializer));
|
||||
const isInvalidInitializer = !(isStringOrNumberLiteralExpression(node.initializer) || isSimpleLiteralEnumReference(node.initializer) || node.initializer.kind === SyntaxKind.TrueKeyword || node.initializer.kind === SyntaxKind.FalseKeyword);
|
||||
const isConstOrReadonly = isDeclarationReadonly(node) || isVariableDeclaration(node) && isVarConst(node);
|
||||
if (isConstOrReadonly && !node.type) {
|
||||
if (isInvalidInitializer) {
|
||||
|
||||
@ -3034,8 +3034,8 @@ namespace ts {
|
||||
/* @internal */ getStringType(): Type;
|
||||
/* @internal */ getNumberType(): Type;
|
||||
/* @internal */ getBooleanType(): Type;
|
||||
/* @internal */ getFalseType(): Type;
|
||||
/* @internal */ getTrueType(): Type;
|
||||
/* @internal */ getFalseType(fresh?: boolean): Type;
|
||||
/* @internal */ getTrueType(fresh?: boolean): Type;
|
||||
/* @internal */ getVoidType(): Type;
|
||||
/* @internal */ getUndefinedType(): Type;
|
||||
/* @internal */ getNullType(): Type;
|
||||
@ -3731,7 +3731,7 @@ namespace ts {
|
||||
Unit = Literal | UniqueESSymbol | Nullable,
|
||||
StringOrNumberLiteral = StringLiteral | NumberLiteral,
|
||||
/* @internal */
|
||||
StringOrNumberLiteralOrUnique = StringOrNumberLiteral | UniqueESSymbol,
|
||||
StringOrNumberLiteralOrUnique = StringLiteral | NumberLiteral | UniqueESSymbol,
|
||||
/* @internal */
|
||||
DefinitelyFalsy = StringLiteral | NumberLiteral | BooleanLiteral | Void | Undefined | Null,
|
||||
PossiblyFalsy = DefinitelyFalsy | String | Number | Boolean,
|
||||
@ -3802,6 +3802,15 @@ namespace ts {
|
||||
intrinsicName: string; // Name of intrinsic type
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface FreshableIntrinsicType extends IntrinsicType {
|
||||
freshType: IntrinsicType; // Fresh version of type
|
||||
regularType: IntrinsicType; // Regular version of type
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export type FreshableType = LiteralType | FreshableIntrinsicType;
|
||||
|
||||
// String literal types (TypeFlags.StringLiteral)
|
||||
// Numeric literal types (TypeFlags.NumberLiteral)
|
||||
export interface LiteralType extends Type {
|
||||
|
||||
@ -110,7 +110,7 @@ namespace ts.codefix {
|
||||
|
||||
function getDefaultValueFromType (checker: TypeChecker, type: Type): Expression | undefined {
|
||||
if (type.flags & TypeFlags.BooleanLiteral) {
|
||||
return type === checker.getFalseType() ? createFalse() : createTrue();
|
||||
return (type === checker.getFalseType() || type === checker.getFalseType(/*fresh*/ true)) ? createFalse() : createTrue();
|
||||
}
|
||||
else if (type.isLiteral()) {
|
||||
return createLiteral(type.value);
|
||||
|
||||
@ -63,7 +63,7 @@ declare const c3 = "abc";
|
||||
declare const c4 = 123;
|
||||
declare const c5 = 123;
|
||||
declare const c6 = -123;
|
||||
declare const c7: boolean;
|
||||
declare const c7 = true;
|
||||
declare const c8 = E.A;
|
||||
declare const c8b = E["non identifier"];
|
||||
declare const c9: {
|
||||
|
||||
@ -82,13 +82,13 @@ function f4(t: true, f: false) {
|
||||
>false : false
|
||||
|
||||
var x1 = t && f;
|
||||
>x1 : boolean
|
||||
>x1 : false
|
||||
>t && f : false
|
||||
>t : true
|
||||
>f : false
|
||||
|
||||
var x2 = f && t;
|
||||
>x2 : boolean
|
||||
>x2 : false
|
||||
>f && t : false
|
||||
>f : false
|
||||
>t : true
|
||||
@ -100,7 +100,7 @@ function f4(t: true, f: false) {
|
||||
>f : false
|
||||
|
||||
var x4 = f || t;
|
||||
>x4 : boolean
|
||||
>x4 : true
|
||||
>f || t : true
|
||||
>f : false
|
||||
>t : true
|
||||
|
||||
@ -82,25 +82,25 @@ function f4(t: true, f: false) {
|
||||
>false : false
|
||||
|
||||
var x1 = t && f;
|
||||
>x1 : boolean
|
||||
>x1 : false
|
||||
>t && f : false
|
||||
>t : true
|
||||
>f : false
|
||||
|
||||
var x2 = f && t;
|
||||
>x2 : boolean
|
||||
>x2 : false
|
||||
>f && t : false
|
||||
>f : false
|
||||
>t : true
|
||||
|
||||
var x3 = t || f;
|
||||
>x3 : boolean
|
||||
>x3 : true
|
||||
>t || f : true
|
||||
>t : true
|
||||
>f : false
|
||||
|
||||
var x4 = f || t;
|
||||
>x4 : boolean
|
||||
>x4 : true
|
||||
>f || t : true
|
||||
>f : false
|
||||
>t : true
|
||||
|
||||
@ -24,6 +24,6 @@ for (const c5 = 0, c6 = 0; c5 < c6;) {
|
||||
|
||||
|
||||
//// [constDeclarations.d.ts]
|
||||
declare const c1: boolean;
|
||||
declare const c1 = false;
|
||||
declare const c2: number;
|
||||
declare const c3 = 0, c4: string, c5: any;
|
||||
|
||||
@ -19,7 +19,7 @@ var M;
|
||||
|
||||
//// [constDeclarations2.d.ts]
|
||||
declare module M {
|
||||
const c1: boolean;
|
||||
const c1 = false;
|
||||
const c2: number;
|
||||
const c3 = 0, c4: string, c5: any;
|
||||
}
|
||||
|
||||
@ -162,7 +162,7 @@ var rc1 = a1 || a3; // any || number is any
|
||||
>a3 : number
|
||||
|
||||
var rc2 = a2 || a3; // boolean || number is boolean | number
|
||||
>rc2 : number | boolean
|
||||
>rc2 : number | true
|
||||
>a2 || a3 : number | true
|
||||
>a2 : boolean
|
||||
>a3 : number
|
||||
@ -222,7 +222,7 @@ var rd1 = a1 || a4; // any || string is any
|
||||
>a4 : string
|
||||
|
||||
var rd2 = a2 || a4; // boolean || string is boolean | string
|
||||
>rd2 : string | boolean
|
||||
>rd2 : string | true
|
||||
>a2 || a4 : string | true
|
||||
>a2 : boolean
|
||||
>a4 : string
|
||||
@ -282,7 +282,7 @@ var re1 = a1 || a5; // any || void is any
|
||||
>a5 : void
|
||||
|
||||
var re2 = a2 || a5; // boolean || void is boolean | void
|
||||
>re2 : boolean | void
|
||||
>re2 : true | void
|
||||
>a2 || a5 : true | void
|
||||
>a2 : boolean
|
||||
>a5 : void
|
||||
@ -342,7 +342,7 @@ var rg1 = a1 || a6; // any || enum is any
|
||||
>a6 : E
|
||||
|
||||
var rg2 = a2 || a6; // boolean || enum is boolean | enum
|
||||
>rg2 : boolean | E
|
||||
>rg2 : true | E
|
||||
>a2 || a6 : true | E
|
||||
>a2 : boolean
|
||||
>a6 : E
|
||||
@ -402,7 +402,7 @@ var rh1 = a1 || a7; // any || object is any
|
||||
>a7 : { a: string; }
|
||||
|
||||
var rh2 = a2 || a7; // boolean || object is boolean | object
|
||||
>rh2 : boolean | { a: string; }
|
||||
>rh2 : true | { a: string; }
|
||||
>a2 || a7 : true | { a: string; }
|
||||
>a2 : boolean
|
||||
>a7 : { a: string; }
|
||||
@ -462,7 +462,7 @@ var ri1 = a1 || a8; // any || array is any
|
||||
>a8 : string[]
|
||||
|
||||
var ri2 = a2 || a8; // boolean || array is boolean | array
|
||||
>ri2 : boolean | string[]
|
||||
>ri2 : true | string[]
|
||||
>a2 || a8 : true | string[]
|
||||
>a2 : boolean
|
||||
>a8 : string[]
|
||||
@ -522,7 +522,7 @@ var rj1 = a1 || null; // any || null is any
|
||||
>null : null
|
||||
|
||||
var rj2 = a2 || null; // boolean || null is boolean
|
||||
>rj2 : boolean
|
||||
>rj2 : true
|
||||
>a2 || null : true
|
||||
>a2 : boolean
|
||||
>null : null
|
||||
@ -582,7 +582,7 @@ var rf1 = a1 || undefined; // any || undefined is any
|
||||
>undefined : undefined
|
||||
|
||||
var rf2 = a2 || undefined; // boolean || undefined is boolean
|
||||
>rf2 : boolean
|
||||
>rf2 : true
|
||||
>a2 || undefined : true
|
||||
>a2 : boolean
|
||||
>undefined : undefined
|
||||
|
||||
@ -371,13 +371,13 @@ function f15(x: 0 | false, y: 1 | "one") {
|
||||
>y : 1 | "one"
|
||||
|
||||
var a = x && y;
|
||||
>a : boolean | 0
|
||||
>a : false | 0
|
||||
>x && y : false | 0
|
||||
>x : false | 0
|
||||
>y : 1 | "one"
|
||||
|
||||
var b = y && x;
|
||||
>b : boolean | 0
|
||||
>b : false | 0
|
||||
>y && x : false | 0
|
||||
>y : 1 | "one"
|
||||
>x : false | 0
|
||||
@ -389,7 +389,7 @@ function f15(x: 0 | false, y: 1 | "one") {
|
||||
>y : 1 | "one"
|
||||
|
||||
var d = y || x;
|
||||
>d : boolean | 0 | 1 | "one"
|
||||
>d : false | 0 | 1 | "one"
|
||||
>y || x : false | 0 | 1 | "one"
|
||||
>y : 1 | "one"
|
||||
>x : false | 0
|
||||
|
||||
@ -371,13 +371,13 @@ function f15(x: 0 | false, y: 1 | "one") {
|
||||
>y : 1 | "one"
|
||||
|
||||
var a = x && y;
|
||||
>a : boolean | 0
|
||||
>a : false | 0
|
||||
>x && y : false | 0
|
||||
>x : false | 0
|
||||
>y : 1 | "one"
|
||||
|
||||
var b = y && x;
|
||||
>b : boolean | 0
|
||||
>b : false | 0
|
||||
>y && x : false | 0
|
||||
>y : 1 | "one"
|
||||
>x : false | 0
|
||||
|
||||
11
tests/baselines/reference/spreadBooleanRespectsFreshness.js
Normal file
11
tests/baselines/reference/spreadBooleanRespectsFreshness.js
Normal file
@ -0,0 +1,11 @@
|
||||
//// [spreadBooleanRespectsFreshness.ts]
|
||||
type Foo = FooBase | FooArray;
|
||||
type FooBase = string | false;
|
||||
type FooArray = FooBase[];
|
||||
|
||||
declare let foo1: Foo;
|
||||
declare let foo2: Foo;
|
||||
foo1 = [...Array.isArray(foo2) ? foo2 : [foo2]];
|
||||
|
||||
//// [spreadBooleanRespectsFreshness.js]
|
||||
foo1 = (Array.isArray(foo2) ? foo2 : [foo2]).slice();
|
||||
@ -0,0 +1,30 @@
|
||||
=== tests/cases/compiler/spreadBooleanRespectsFreshness.ts ===
|
||||
type Foo = FooBase | FooArray;
|
||||
>Foo : Symbol(Foo, Decl(spreadBooleanRespectsFreshness.ts, 0, 0))
|
||||
>FooBase : Symbol(FooBase, Decl(spreadBooleanRespectsFreshness.ts, 0, 30))
|
||||
>FooArray : Symbol(FooArray, Decl(spreadBooleanRespectsFreshness.ts, 1, 30))
|
||||
|
||||
type FooBase = string | false;
|
||||
>FooBase : Symbol(FooBase, Decl(spreadBooleanRespectsFreshness.ts, 0, 30))
|
||||
|
||||
type FooArray = FooBase[];
|
||||
>FooArray : Symbol(FooArray, Decl(spreadBooleanRespectsFreshness.ts, 1, 30))
|
||||
>FooBase : Symbol(FooBase, Decl(spreadBooleanRespectsFreshness.ts, 0, 30))
|
||||
|
||||
declare let foo1: Foo;
|
||||
>foo1 : Symbol(foo1, Decl(spreadBooleanRespectsFreshness.ts, 4, 11))
|
||||
>Foo : Symbol(Foo, Decl(spreadBooleanRespectsFreshness.ts, 0, 0))
|
||||
|
||||
declare let foo2: Foo;
|
||||
>foo2 : Symbol(foo2, Decl(spreadBooleanRespectsFreshness.ts, 5, 11))
|
||||
>Foo : Symbol(Foo, Decl(spreadBooleanRespectsFreshness.ts, 0, 0))
|
||||
|
||||
foo1 = [...Array.isArray(foo2) ? foo2 : [foo2]];
|
||||
>foo1 : Symbol(foo1, Decl(spreadBooleanRespectsFreshness.ts, 4, 11))
|
||||
>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
|
||||
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
|
||||
>foo2 : Symbol(foo2, Decl(spreadBooleanRespectsFreshness.ts, 5, 11))
|
||||
>foo2 : Symbol(foo2, Decl(spreadBooleanRespectsFreshness.ts, 5, 11))
|
||||
>foo2 : Symbol(foo2, Decl(spreadBooleanRespectsFreshness.ts, 5, 11))
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
=== tests/cases/compiler/spreadBooleanRespectsFreshness.ts ===
|
||||
type Foo = FooBase | FooArray;
|
||||
>Foo : Foo
|
||||
|
||||
type FooBase = string | false;
|
||||
>FooBase : FooBase
|
||||
>false : false
|
||||
|
||||
type FooArray = FooBase[];
|
||||
>FooArray : FooBase[]
|
||||
|
||||
declare let foo1: Foo;
|
||||
>foo1 : Foo
|
||||
|
||||
declare let foo2: Foo;
|
||||
>foo2 : Foo
|
||||
|
||||
foo1 = [...Array.isArray(foo2) ? foo2 : [foo2]];
|
||||
>foo1 = [...Array.isArray(foo2) ? foo2 : [foo2]] : FooBase[]
|
||||
>foo1 : Foo
|
||||
>[...Array.isArray(foo2) ? foo2 : [foo2]] : FooBase[]
|
||||
>...Array.isArray(foo2) ? foo2 : [foo2] : FooBase
|
||||
>Array.isArray(foo2) ? foo2 : [foo2] : FooBase[]
|
||||
>Array.isArray(foo2) : boolean
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>foo2 : Foo
|
||||
>foo2 : FooBase[]
|
||||
>[foo2] : FooBase[]
|
||||
>foo2 : FooBase
|
||||
|
||||
7
tests/cases/compiler/spreadBooleanRespectsFreshness.ts
Normal file
7
tests/cases/compiler/spreadBooleanRespectsFreshness.ts
Normal file
@ -0,0 +1,7 @@
|
||||
type Foo = FooBase | FooArray;
|
||||
type FooBase = string | false;
|
||||
type FooArray = FooBase[];
|
||||
|
||||
declare let foo1: Foo;
|
||||
declare let foo2: Foo;
|
||||
foo1 = [...Array.isArray(foo2) ? foo2 : [foo2]];
|
||||
Loading…
x
Reference in New Issue
Block a user