Merge remote-tracking branch 'origin/master' into usePromise
This commit is contained in:
commit
143edff303
24 changed files with 863 additions and 17 deletions
|
@ -1045,7 +1045,35 @@ namespace ts {
|
|||
if (node.finallyBlock) {
|
||||
// in finally flow is combined from pre-try/flow from try/flow from catch
|
||||
// pre-flow is necessary to make sure that finally is reachable even if finally flows in both try and finally blocks are unreachable
|
||||
addAntecedent(preFinallyLabel, preTryFlow);
|
||||
|
||||
// also for finally blocks we inject two extra edges into the flow graph.
|
||||
// first -> edge that connects pre-try flow with the label at the beginning of the finally block, it has lock associated with it
|
||||
// second -> edge that represents post-finally flow.
|
||||
// these edges are used in following scenario:
|
||||
// let a; (1)
|
||||
// try { a = someOperation(); (2)}
|
||||
// finally { (3) console.log(a) } (4)
|
||||
// (5) a
|
||||
|
||||
// flow graph for this case looks roughly like this (arrows show ):
|
||||
// (1-pre-try-flow) <--.. <-- (2-post-try-flow)
|
||||
// ^ ^
|
||||
// |*****(3-pre-finally-label) -----|
|
||||
// ^
|
||||
// |-- ... <-- (4-post-finally-label) <--- (5)
|
||||
// In case when we walk the flow starting from inside the finally block we want to take edge '*****' into account
|
||||
// since it ensures that finally is always reachable. However when we start outside the finally block and go through label (5)
|
||||
// then edge '*****' should be discarded because label 4 is only reachable if post-finally label-4 is reachable
|
||||
// Simply speaking code inside finally block is treated as reachable as pre-try-flow
|
||||
// since we conservatively assume that any line in try block can throw or return in which case we'll enter finally.
|
||||
// However code after finally is reachable only if control flow was not abrupted in try/catch or finally blocks - it should be composed from
|
||||
// final flows of these blocks without taking pre-try flow into account.
|
||||
//
|
||||
// extra edges that we inject allows to control this behavior
|
||||
// if when walking the flow we step on post-finally edge - we can mark matching pre-finally edge as locked so it will be skipped.
|
||||
const preFinallyFlow: PreFinallyFlow = { flags: FlowFlags.PreFinally, antecedent: preTryFlow, lock: {} };
|
||||
addAntecedent(preFinallyLabel, preFinallyFlow);
|
||||
|
||||
currentFlow = finishFlowLabel(preFinallyLabel);
|
||||
bind(node.finallyBlock);
|
||||
// if flow after finally is unreachable - keep it
|
||||
|
@ -1061,6 +1089,11 @@ namespace ts {
|
|||
: unreachableFlow;
|
||||
}
|
||||
}
|
||||
if (!(currentFlow.flags & FlowFlags.Unreachable)) {
|
||||
const afterFinallyFlow: AfterFinallyFlow = { flags: FlowFlags.AfterFinally, antecedent: currentFlow };
|
||||
preFinallyFlow.lock = afterFinallyFlow;
|
||||
currentFlow = afterFinallyFlow;
|
||||
}
|
||||
}
|
||||
else {
|
||||
currentFlow = finishFlowLabel(preFinallyLabel);
|
||||
|
|
|
@ -2690,7 +2690,11 @@ namespace ts {
|
|||
writePunctuation(writer, SyntaxKind.ColonToken);
|
||||
writeSpace(writer);
|
||||
|
||||
buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, symbolStack);
|
||||
let type = getTypeOfSymbol(p);
|
||||
if (isRequiredInitializedParameter(parameterNode)) {
|
||||
type = includeFalsyTypes(type, TypeFlags.Undefined);
|
||||
}
|
||||
buildTypeDisplay(type, writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
|
||||
function buildBindingPatternDisplay(bindingPattern: BindingPattern, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
|
@ -3271,6 +3275,16 @@ namespace ts {
|
|||
return strictNullChecks && optional ? includeFalsyTypes(type, TypeFlags.Undefined) : type;
|
||||
}
|
||||
|
||||
/** remove undefined from the annotated type of a parameter when there is an initializer (that doesn't include undefined) */
|
||||
function removeOptionalityFromAnnotation(annotatedType: Type, declaration: VariableLikeDeclaration): Type {
|
||||
const annotationIncludesUndefined = strictNullChecks &&
|
||||
declaration.kind === SyntaxKind.Parameter &&
|
||||
declaration.initializer &&
|
||||
getFalsyFlags(annotatedType) & TypeFlags.Undefined &&
|
||||
!(getFalsyFlags(checkExpression(declaration.initializer)) & TypeFlags.Undefined);
|
||||
return annotationIncludesUndefined ? getNonNullableType(annotatedType) : annotatedType;
|
||||
}
|
||||
|
||||
// Return the inferred type for a variable, parameter, or property declaration
|
||||
function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration, includeOptionality: boolean): Type {
|
||||
if (declaration.flags & NodeFlags.JavaScriptFile) {
|
||||
|
@ -3304,7 +3318,8 @@ namespace ts {
|
|||
|
||||
// Use type from type annotation if one is present
|
||||
if (declaration.type) {
|
||||
return addOptionality(getTypeFromTypeNode(declaration.type), /*optional*/ declaration.questionToken && includeOptionality);
|
||||
const declaredType = removeOptionalityFromAnnotation(getTypeFromTypeNode(declaration.type), declaration);
|
||||
return addOptionality(declaredType, /*optional*/ declaration.questionToken && includeOptionality);
|
||||
}
|
||||
|
||||
if ((compilerOptions.noImplicitAny || declaration.flags & NodeFlags.JavaScriptFile) &&
|
||||
|
@ -5198,6 +5213,12 @@ namespace ts {
|
|||
Debug.assert(parameterIndex >= 0);
|
||||
return parameterIndex >= signature.minArgumentCount;
|
||||
}
|
||||
const iife = getImmediatelyInvokedFunctionExpression(node.parent);
|
||||
if (iife) {
|
||||
return !node.type &&
|
||||
!node.dotDotDotToken &&
|
||||
indexOf((node.parent as SignatureDeclaration).parameters, node) >= iife.arguments.length;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -7762,16 +7783,36 @@ namespace ts {
|
|||
if (target.flags & TypeFlags.Union && containsType(targetTypes, source)) {
|
||||
return Ternary.True;
|
||||
}
|
||||
const len = targetTypes.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
const related = isRelatedTo(source, targetTypes[i], reportErrors && i === len - 1);
|
||||
for (const type of targetTypes) {
|
||||
const related = isRelatedTo(source, type, /*reportErrors*/ false);
|
||||
if (related) {
|
||||
return related;
|
||||
}
|
||||
}
|
||||
if (reportErrors) {
|
||||
const discriminantType = findMatchingDiscriminantType(source, target);
|
||||
isRelatedTo(source, discriminantType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true);
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
|
||||
function findMatchingDiscriminantType(source: Type, target: UnionOrIntersectionType) {
|
||||
const sourceProperties = getPropertiesOfObjectType(source);
|
||||
if (sourceProperties) {
|
||||
for (const sourceProperty of sourceProperties) {
|
||||
if (isDiscriminantProperty(target, sourceProperty.name)) {
|
||||
const sourceType = getTypeOfSymbol(sourceProperty);
|
||||
for (const type of target.types) {
|
||||
const targetType = getTypeOfPropertyOfType(type, sourceProperty.name);
|
||||
if (targetType && isRelatedTo(sourceType, targetType)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function typeRelatedToEachType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
|
||||
let result = Ternary.True;
|
||||
const targetTypes = target.types;
|
||||
|
@ -8592,7 +8633,7 @@ namespace ts {
|
|||
if (flags & TypeFlags.Void) types.push(voidType);
|
||||
if (flags & TypeFlags.Undefined) types.push(undefinedType);
|
||||
if (flags & TypeFlags.Null) types.push(nullType);
|
||||
return getUnionType(types, /*subtypeReduction*/ true);
|
||||
return getUnionType(types);
|
||||
}
|
||||
|
||||
function removeDefinitelyFalsyTypes(type: Type): Type {
|
||||
|
@ -9875,7 +9916,19 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
let type: FlowType;
|
||||
if (flow.flags & FlowFlags.Assignment) {
|
||||
if (flow.flags & FlowFlags.AfterFinally) {
|
||||
// block flow edge: finally -> pre-try (for larger explanation check comment in binder.ts - bindTryStatement
|
||||
(<AfterFinallyFlow>flow).locked = true;
|
||||
type = getTypeAtFlowNode((<AfterFinallyFlow>flow).antecedent);
|
||||
(<AfterFinallyFlow>flow).locked = false;
|
||||
}
|
||||
else if (flow.flags & FlowFlags.PreFinally) {
|
||||
// locked pre-finally flows are filtered out in getTypeAtFlowBranchLabel
|
||||
// so here just redirect to antecedent
|
||||
flow = (<PreFinallyFlow>flow).antecedent;
|
||||
continue;
|
||||
}
|
||||
else if (flow.flags & FlowFlags.Assignment) {
|
||||
type = getTypeAtFlowAssignment(<FlowAssignment>flow);
|
||||
if (!type) {
|
||||
flow = (<FlowAssignment>flow).antecedent;
|
||||
|
@ -10031,6 +10084,12 @@ namespace ts {
|
|||
let subtypeReduction = false;
|
||||
let seenIncomplete = false;
|
||||
for (const antecedent of flow.antecedents) {
|
||||
if (antecedent.flags & FlowFlags.PreFinally && (<PreFinallyFlow>antecedent).lock.locked) {
|
||||
// if flow correspond to branch from pre-try to finally and this branch is locked - this means that
|
||||
// we initially have started following the flow outside the finally block.
|
||||
// in this case we should ignore this branch.
|
||||
continue;
|
||||
}
|
||||
const flowType = getTypeAtFlowNode(antecedent);
|
||||
const type = getTypeFromFlowType(flowType);
|
||||
// If the type at a particular antecedent path is the declared type and the
|
||||
|
@ -20710,6 +20769,13 @@ namespace ts {
|
|||
return false;
|
||||
}
|
||||
|
||||
function isRequiredInitializedParameter(parameter: ParameterDeclaration) {
|
||||
return strictNullChecks &&
|
||||
!isOptionalParameter(parameter) &&
|
||||
parameter.initializer &&
|
||||
!(getModifierFlags(parameter) & ModifierFlags.ParameterPropertyModifier);
|
||||
}
|
||||
|
||||
function getNodeCheckFlags(node: Node): NodeCheckFlags {
|
||||
node = getParseTreeNode(node);
|
||||
return node ? getNodeLinks(node).flags : undefined;
|
||||
|
@ -20801,10 +20867,12 @@ namespace ts {
|
|||
function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
|
||||
// Get type of the symbol if this is the valid symbol otherwise get type at location
|
||||
const symbol = getSymbolOfNode(declaration);
|
||||
const type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature))
|
||||
let type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature))
|
||||
? getWidenedLiteralType(getTypeOfSymbol(symbol))
|
||||
: unknownType;
|
||||
|
||||
if (flags & TypeFormatFlags.AddUndefined) {
|
||||
type = includeFalsyTypes(type, TypeFlags.Undefined);
|
||||
}
|
||||
getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
|
||||
}
|
||||
|
||||
|
@ -20903,6 +20971,7 @@ namespace ts {
|
|||
isTopLevelValueImportEqualsWithEntityName,
|
||||
isDeclarationVisible,
|
||||
isImplementationOfOverload,
|
||||
isRequiredInitializedParameter,
|
||||
writeTypeOfDeclaration,
|
||||
writeReturnTypeOfSignatureDeclaration,
|
||||
writeTypeOfExpression,
|
||||
|
|
|
@ -324,13 +324,20 @@ namespace ts {
|
|||
function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, type: TypeNode, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) {
|
||||
writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
|
||||
write(": ");
|
||||
if (type) {
|
||||
|
||||
// use the checker's type, not the declared type,
|
||||
// for non-optional initialized parameters that aren't a parameter property
|
||||
const shouldUseResolverType = declaration.kind === SyntaxKind.Parameter &&
|
||||
resolver.isRequiredInitializedParameter(declaration as ParameterDeclaration);
|
||||
if (type && !shouldUseResolverType) {
|
||||
// Write the type
|
||||
emitType(type);
|
||||
}
|
||||
else {
|
||||
errorNameNode = declaration.name;
|
||||
resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer);
|
||||
const format = TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue |
|
||||
(shouldUseResolverType ? TypeFormatFlags.AddUndefined : 0);
|
||||
resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, format, writer);
|
||||
errorNameNode = undefined;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2071,10 +2071,25 @@
|
|||
ArrayMutation = 1 << 8, // Potential array mutation
|
||||
Referenced = 1 << 9, // Referenced as antecedent once
|
||||
Shared = 1 << 10, // Referenced as antecedent more than once
|
||||
PreFinally = 1 << 11, // Injected edge that links pre-finally label and pre-try flow
|
||||
AfterFinally = 1 << 12, // Injected edge that links post-finally flow with the rest of the graph
|
||||
Label = BranchLabel | LoopLabel,
|
||||
Condition = TrueCondition | FalseCondition
|
||||
}
|
||||
|
||||
export interface FlowLock {
|
||||
locked?: boolean;
|
||||
}
|
||||
|
||||
export interface AfterFinallyFlow extends FlowNode, FlowLock {
|
||||
antecedent: FlowNode;
|
||||
}
|
||||
|
||||
export interface PreFinallyFlow extends FlowNode {
|
||||
antecedent: FlowNode;
|
||||
lock: FlowLock;
|
||||
}
|
||||
|
||||
export interface FlowNode {
|
||||
flags: FlowFlags;
|
||||
id?: number; // Node id used by flow type cache in checker
|
||||
|
@ -2474,7 +2489,8 @@
|
|||
InFirstTypeArgument = 0x00000100, // Writing first type argument of the instantiated type
|
||||
InTypeAlias = 0x00000200, // Writing type in type alias declaration
|
||||
UseTypeAliasValue = 0x00000400, // Serialize the type instead of using type-alias. This is needed when we emit declaration file.
|
||||
SuppressAnyReturnType = 0x00000800, // If the return type is any-like, don't offer a return type.
|
||||
SuppressAnyReturnType = 0x00000800, // If the return type is any-like, don't offer a return type.
|
||||
AddUndefined = 0x00001000, // Add undefined to types of initialized, non-optional parameters
|
||||
}
|
||||
|
||||
export const enum SymbolFormatFlags {
|
||||
|
@ -2579,6 +2595,7 @@
|
|||
isDeclarationVisible(node: Declaration): boolean;
|
||||
collectLinkedAliases(node: Identifier): Node[];
|
||||
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
|
||||
isRequiredInitializedParameter(node: ParameterDeclaration): boolean;
|
||||
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
|
|
|
@ -253,8 +253,8 @@ let eleven = (o => o.a(11))({ a: function(n) { return n; } });
|
|||
// missing arguments
|
||||
(function(x, undefined) { return x; })(42);
|
||||
>(function(x, undefined) { return x; })(42) : number
|
||||
>(function(x, undefined) { return x; }) : (x: number, undefined: any) => number
|
||||
>function(x, undefined) { return x; } : (x: number, undefined: any) => number
|
||||
>(function(x, undefined) { return x; }) : (x: number, undefined?: any) => number
|
||||
>function(x, undefined) { return x; } : (x: number, undefined?: any) => number
|
||||
>x : number
|
||||
>undefined : any
|
||||
>x : number
|
||||
|
@ -262,8 +262,8 @@ let eleven = (o => o.a(11))({ a: function(n) { return n; } });
|
|||
|
||||
((x, y, z) => 42)();
|
||||
>((x, y, z) => 42)() : number
|
||||
>((x, y, z) => 42) : (x: any, y: any, z: any) => number
|
||||
>(x, y, z) => 42 : (x: any, y: any, z: any) => number
|
||||
>((x, y, z) => 42) : (x?: any, y?: any, z?: any) => number
|
||||
>(x, y, z) => 42 : (x?: any, y?: any, z?: any) => number
|
||||
>x : any
|
||||
>y : any
|
||||
>z : any
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
//// [defaultParameterAddsUndefinedWithStrictNullChecks.ts]
|
||||
function f(addUndefined1 = "J", addUndefined2?: number) {
|
||||
return addUndefined1.length + (addUndefined2 || 0);
|
||||
}
|
||||
function g(addUndefined = "J", addDefined: number) {
|
||||
return addUndefined.length + addDefined;
|
||||
}
|
||||
let total = f() + f('a', 1) + f('b') + f(undefined, 2);
|
||||
total = g('c', 3) + g(undefined, 4);
|
||||
|
||||
function foo1(x: string = "string", b: number) {
|
||||
x.length;
|
||||
}
|
||||
|
||||
function foo2(x = "string", b: number) {
|
||||
x.length; // ok, should be string
|
||||
}
|
||||
|
||||
function foo3(x: string | undefined = "string", b: number) {
|
||||
x.length; // ok, should be string
|
||||
}
|
||||
|
||||
function foo4(x: string | undefined = undefined, b: number) {
|
||||
x; // should be string | undefined
|
||||
}
|
||||
|
||||
|
||||
|
||||
// .d.ts should have `string | undefined` for foo1, foo2, foo3 and foo4
|
||||
foo1(undefined, 1);
|
||||
foo2(undefined, 1);
|
||||
foo3(undefined, 1);
|
||||
foo4(undefined, 1);
|
||||
|
||||
|
||||
function removeUndefinedButNotFalse(x = true) {
|
||||
if (x === false) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
declare const cond: boolean;
|
||||
function removeNothing(y = cond ? true : undefined) {
|
||||
if (y !== undefined) {
|
||||
if (y === false) {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//// [defaultParameterAddsUndefinedWithStrictNullChecks.js]
|
||||
function f(addUndefined1, addUndefined2) {
|
||||
if (addUndefined1 === void 0) { addUndefined1 = "J"; }
|
||||
return addUndefined1.length + (addUndefined2 || 0);
|
||||
}
|
||||
function g(addUndefined, addDefined) {
|
||||
if (addUndefined === void 0) { addUndefined = "J"; }
|
||||
return addUndefined.length + addDefined;
|
||||
}
|
||||
var total = f() + f('a', 1) + f('b') + f(undefined, 2);
|
||||
total = g('c', 3) + g(undefined, 4);
|
||||
function foo1(x, b) {
|
||||
if (x === void 0) { x = "string"; }
|
||||
x.length;
|
||||
}
|
||||
function foo2(x, b) {
|
||||
if (x === void 0) { x = "string"; }
|
||||
x.length; // ok, should be string
|
||||
}
|
||||
function foo3(x, b) {
|
||||
if (x === void 0) { x = "string"; }
|
||||
x.length; // ok, should be string
|
||||
}
|
||||
function foo4(x, b) {
|
||||
if (x === void 0) { x = undefined; }
|
||||
x; // should be string | undefined
|
||||
}
|
||||
// .d.ts should have `string | undefined` for foo1, foo2, foo3 and foo4
|
||||
foo1(undefined, 1);
|
||||
foo2(undefined, 1);
|
||||
foo3(undefined, 1);
|
||||
foo4(undefined, 1);
|
||||
function removeUndefinedButNotFalse(x) {
|
||||
if (x === void 0) { x = true; }
|
||||
if (x === false) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
function removeNothing(y) {
|
||||
if (y === void 0) { y = cond ? true : undefined; }
|
||||
if (y !== undefined) {
|
||||
if (y === false) {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//// [defaultParameterAddsUndefinedWithStrictNullChecks.d.ts]
|
||||
declare function f(addUndefined1?: string, addUndefined2?: number): number;
|
||||
declare function g(addUndefined: string | undefined, addDefined: number): number;
|
||||
declare let total: number;
|
||||
declare function foo1(x: string | undefined, b: number): void;
|
||||
declare function foo2(x: string | undefined, b: number): void;
|
||||
declare function foo3(x: string | undefined, b: number): void;
|
||||
declare function foo4(x: string | undefined, b: number): void;
|
||||
declare function removeUndefinedButNotFalse(x?: boolean): false | undefined;
|
||||
declare const cond: boolean;
|
||||
declare function removeNothing(y?: boolean | undefined): boolean;
|
|
@ -0,0 +1,135 @@
|
|||
=== tests/cases/compiler/defaultParameterAddsUndefinedWithStrictNullChecks.ts ===
|
||||
function f(addUndefined1 = "J", addUndefined2?: number) {
|
||||
>f : Symbol(f, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 0, 0))
|
||||
>addUndefined1 : Symbol(addUndefined1, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 0, 11))
|
||||
>addUndefined2 : Symbol(addUndefined2, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 0, 31))
|
||||
|
||||
return addUndefined1.length + (addUndefined2 || 0);
|
||||
>addUndefined1.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>addUndefined1 : Symbol(addUndefined1, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 0, 11))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>addUndefined2 : Symbol(addUndefined2, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 0, 31))
|
||||
}
|
||||
function g(addUndefined = "J", addDefined: number) {
|
||||
>g : Symbol(g, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 2, 1))
|
||||
>addUndefined : Symbol(addUndefined, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 3, 11))
|
||||
>addDefined : Symbol(addDefined, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 3, 30))
|
||||
|
||||
return addUndefined.length + addDefined;
|
||||
>addUndefined.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>addUndefined : Symbol(addUndefined, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 3, 11))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>addDefined : Symbol(addDefined, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 3, 30))
|
||||
}
|
||||
let total = f() + f('a', 1) + f('b') + f(undefined, 2);
|
||||
>total : Symbol(total, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 6, 3))
|
||||
>f : Symbol(f, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 0, 0))
|
||||
>f : Symbol(f, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 0, 0))
|
||||
>f : Symbol(f, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 0, 0))
|
||||
>f : Symbol(f, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 0, 0))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
total = g('c', 3) + g(undefined, 4);
|
||||
>total : Symbol(total, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 6, 3))
|
||||
>g : Symbol(g, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 2, 1))
|
||||
>g : Symbol(g, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 2, 1))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
function foo1(x: string = "string", b: number) {
|
||||
>foo1 : Symbol(foo1, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 7, 36))
|
||||
>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 9, 14))
|
||||
>b : Symbol(b, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 9, 35))
|
||||
|
||||
x.length;
|
||||
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 9, 14))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
|
||||
function foo2(x = "string", b: number) {
|
||||
>foo2 : Symbol(foo2, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 11, 1))
|
||||
>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 13, 14))
|
||||
>b : Symbol(b, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 13, 27))
|
||||
|
||||
x.length; // ok, should be string
|
||||
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 13, 14))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
|
||||
function foo3(x: string | undefined = "string", b: number) {
|
||||
>foo3 : Symbol(foo3, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 15, 1))
|
||||
>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 17, 14))
|
||||
>b : Symbol(b, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 17, 47))
|
||||
|
||||
x.length; // ok, should be string
|
||||
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 17, 14))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
|
||||
function foo4(x: string | undefined = undefined, b: number) {
|
||||
>foo4 : Symbol(foo4, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 19, 1))
|
||||
>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 21, 14))
|
||||
>undefined : Symbol(undefined)
|
||||
>b : Symbol(b, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 21, 48))
|
||||
|
||||
x; // should be string | undefined
|
||||
>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 21, 14))
|
||||
}
|
||||
|
||||
|
||||
|
||||
// .d.ts should have `string | undefined` for foo1, foo2, foo3 and foo4
|
||||
foo1(undefined, 1);
|
||||
>foo1 : Symbol(foo1, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 7, 36))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
foo2(undefined, 1);
|
||||
>foo2 : Symbol(foo2, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 11, 1))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
foo3(undefined, 1);
|
||||
>foo3 : Symbol(foo3, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 15, 1))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
foo4(undefined, 1);
|
||||
>foo4 : Symbol(foo4, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 19, 1))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
|
||||
function removeUndefinedButNotFalse(x = true) {
|
||||
>removeUndefinedButNotFalse : Symbol(removeUndefinedButNotFalse, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 31, 19))
|
||||
>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 34, 36))
|
||||
|
||||
if (x === false) {
|
||||
>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 34, 36))
|
||||
|
||||
return x;
|
||||
>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 34, 36))
|
||||
}
|
||||
}
|
||||
|
||||
declare const cond: boolean;
|
||||
>cond : Symbol(cond, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 40, 13))
|
||||
|
||||
function removeNothing(y = cond ? true : undefined) {
|
||||
>removeNothing : Symbol(removeNothing, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 40, 28))
|
||||
>y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 41, 23))
|
||||
>cond : Symbol(cond, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 40, 13))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
if (y !== undefined) {
|
||||
>y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 41, 23))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
if (y === false) {
|
||||
>y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 41, 23))
|
||||
|
||||
return y;
|
||||
>y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 41, 23))
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
=== tests/cases/compiler/defaultParameterAddsUndefinedWithStrictNullChecks.ts ===
|
||||
function f(addUndefined1 = "J", addUndefined2?: number) {
|
||||
>f : (addUndefined1?: string, addUndefined2?: number | undefined) => number
|
||||
>addUndefined1 : string
|
||||
>"J" : "J"
|
||||
>addUndefined2 : number | undefined
|
||||
|
||||
return addUndefined1.length + (addUndefined2 || 0);
|
||||
>addUndefined1.length + (addUndefined2 || 0) : number
|
||||
>addUndefined1.length : number
|
||||
>addUndefined1 : string
|
||||
>length : number
|
||||
>(addUndefined2 || 0) : number
|
||||
>addUndefined2 || 0 : number
|
||||
>addUndefined2 : number | undefined
|
||||
>0 : 0
|
||||
}
|
||||
function g(addUndefined = "J", addDefined: number) {
|
||||
>g : (addUndefined: string | undefined, addDefined: number) => number
|
||||
>addUndefined : string
|
||||
>"J" : "J"
|
||||
>addDefined : number
|
||||
|
||||
return addUndefined.length + addDefined;
|
||||
>addUndefined.length + addDefined : number
|
||||
>addUndefined.length : number
|
||||
>addUndefined : string
|
||||
>length : number
|
||||
>addDefined : number
|
||||
}
|
||||
let total = f() + f('a', 1) + f('b') + f(undefined, 2);
|
||||
>total : number
|
||||
>f() + f('a', 1) + f('b') + f(undefined, 2) : number
|
||||
>f() + f('a', 1) + f('b') : number
|
||||
>f() + f('a', 1) : number
|
||||
>f() : number
|
||||
>f : (addUndefined1?: string, addUndefined2?: number | undefined) => number
|
||||
>f('a', 1) : number
|
||||
>f : (addUndefined1?: string, addUndefined2?: number | undefined) => number
|
||||
>'a' : "a"
|
||||
>1 : 1
|
||||
>f('b') : number
|
||||
>f : (addUndefined1?: string, addUndefined2?: number | undefined) => number
|
||||
>'b' : "b"
|
||||
>f(undefined, 2) : number
|
||||
>f : (addUndefined1?: string, addUndefined2?: number | undefined) => number
|
||||
>undefined : undefined
|
||||
>2 : 2
|
||||
|
||||
total = g('c', 3) + g(undefined, 4);
|
||||
>total = g('c', 3) + g(undefined, 4) : number
|
||||
>total : number
|
||||
>g('c', 3) + g(undefined, 4) : number
|
||||
>g('c', 3) : number
|
||||
>g : (addUndefined: string | undefined, addDefined: number) => number
|
||||
>'c' : "c"
|
||||
>3 : 3
|
||||
>g(undefined, 4) : number
|
||||
>g : (addUndefined: string | undefined, addDefined: number) => number
|
||||
>undefined : undefined
|
||||
>4 : 4
|
||||
|
||||
function foo1(x: string = "string", b: number) {
|
||||
>foo1 : (x: string | undefined, b: number) => void
|
||||
>x : string
|
||||
>"string" : "string"
|
||||
>b : number
|
||||
|
||||
x.length;
|
||||
>x.length : number
|
||||
>x : string
|
||||
>length : number
|
||||
}
|
||||
|
||||
function foo2(x = "string", b: number) {
|
||||
>foo2 : (x: string | undefined, b: number) => void
|
||||
>x : string
|
||||
>"string" : "string"
|
||||
>b : number
|
||||
|
||||
x.length; // ok, should be string
|
||||
>x.length : number
|
||||
>x : string
|
||||
>length : number
|
||||
}
|
||||
|
||||
function foo3(x: string | undefined = "string", b: number) {
|
||||
>foo3 : (x: string | undefined, b: number) => void
|
||||
>x : string
|
||||
>"string" : "string"
|
||||
>b : number
|
||||
|
||||
x.length; // ok, should be string
|
||||
>x.length : number
|
||||
>x : string
|
||||
>length : number
|
||||
}
|
||||
|
||||
function foo4(x: string | undefined = undefined, b: number) {
|
||||
>foo4 : (x: string | undefined, b: number) => void
|
||||
>x : string | undefined
|
||||
>undefined : undefined
|
||||
>b : number
|
||||
|
||||
x; // should be string | undefined
|
||||
>x : string | undefined
|
||||
}
|
||||
|
||||
|
||||
|
||||
// .d.ts should have `string | undefined` for foo1, foo2, foo3 and foo4
|
||||
foo1(undefined, 1);
|
||||
>foo1(undefined, 1) : void
|
||||
>foo1 : (x: string | undefined, b: number) => void
|
||||
>undefined : undefined
|
||||
>1 : 1
|
||||
|
||||
foo2(undefined, 1);
|
||||
>foo2(undefined, 1) : void
|
||||
>foo2 : (x: string | undefined, b: number) => void
|
||||
>undefined : undefined
|
||||
>1 : 1
|
||||
|
||||
foo3(undefined, 1);
|
||||
>foo3(undefined, 1) : void
|
||||
>foo3 : (x: string | undefined, b: number) => void
|
||||
>undefined : undefined
|
||||
>1 : 1
|
||||
|
||||
foo4(undefined, 1);
|
||||
>foo4(undefined, 1) : void
|
||||
>foo4 : (x: string | undefined, b: number) => void
|
||||
>undefined : undefined
|
||||
>1 : 1
|
||||
|
||||
|
||||
function removeUndefinedButNotFalse(x = true) {
|
||||
>removeUndefinedButNotFalse : (x?: boolean) => false | undefined
|
||||
>x : boolean
|
||||
>true : true
|
||||
|
||||
if (x === false) {
|
||||
>x === false : boolean
|
||||
>x : boolean
|
||||
>false : false
|
||||
|
||||
return x;
|
||||
>x : false
|
||||
}
|
||||
}
|
||||
|
||||
declare const cond: boolean;
|
||||
>cond : boolean
|
||||
|
||||
function removeNothing(y = cond ? true : undefined) {
|
||||
>removeNothing : (y?: boolean | undefined) => boolean
|
||||
>y : boolean | undefined
|
||||
>cond ? true : undefined : true | undefined
|
||||
>cond : boolean
|
||||
>true : true
|
||||
>undefined : undefined
|
||||
|
||||
if (y !== undefined) {
|
||||
>y !== undefined : boolean
|
||||
>y : boolean | undefined
|
||||
>undefined : undefined
|
||||
|
||||
if (y === false) {
|
||||
>y === false : boolean
|
||||
>y : boolean
|
||||
>false : false
|
||||
|
||||
return y;
|
||||
>y : false
|
||||
}
|
||||
}
|
||||
return true;
|
||||
>true : true
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
tests/cases/compiler/discriminatedUnionErrorMessage.ts(8,5): error TS2322: Type '{ kind: "sq"; x: number; y: number; }' is not assignable to type 'Shape'.
|
||||
Type '{ kind: "sq"; x: number; y: number; }' is not assignable to type 'Square'.
|
||||
Property 'size' is missing in type '{ kind: "sq"; x: number; y: number; }'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/discriminatedUnionErrorMessage.ts (1 errors) ====
|
||||
type Square = { kind: "sq", size: number }
|
||||
type Rectangle = { kind: "rt", x: number, y: number }
|
||||
type Circle = { kind: "cr", radius: number }
|
||||
type Shape =
|
||||
| Square
|
||||
| Rectangle
|
||||
| Circle;
|
||||
let shape: Shape = {
|
||||
~~~~~
|
||||
!!! error TS2322: Type '{ kind: "sq"; x: number; y: number; }' is not assignable to type 'Shape'.
|
||||
!!! error TS2322: Type '{ kind: "sq"; x: number; y: number; }' is not assignable to type 'Square'.
|
||||
!!! error TS2322: Property 'size' is missing in type '{ kind: "sq"; x: number; y: number; }'.
|
||||
kind: "sq",
|
||||
x: 12,
|
||||
y: 13,
|
||||
}
|
||||
|
21
tests/baselines/reference/discriminatedUnionErrorMessage.js
Normal file
21
tests/baselines/reference/discriminatedUnionErrorMessage.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
//// [discriminatedUnionErrorMessage.ts]
|
||||
type Square = { kind: "sq", size: number }
|
||||
type Rectangle = { kind: "rt", x: number, y: number }
|
||||
type Circle = { kind: "cr", radius: number }
|
||||
type Shape =
|
||||
| Square
|
||||
| Rectangle
|
||||
| Circle;
|
||||
let shape: Shape = {
|
||||
kind: "sq",
|
||||
x: 12,
|
||||
y: 13,
|
||||
}
|
||||
|
||||
|
||||
//// [discriminatedUnionErrorMessage.js]
|
||||
var shape = {
|
||||
kind: "sq",
|
||||
x: 12,
|
||||
y: 13
|
||||
};
|
25
tests/baselines/reference/flowAfterFinally1.js
Normal file
25
tests/baselines/reference/flowAfterFinally1.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
//// [flowAfterFinally1.ts]
|
||||
declare function openFile(): void
|
||||
declare function closeFile(): void
|
||||
declare function someOperation(): {}
|
||||
|
||||
var result: {}
|
||||
openFile()
|
||||
try {
|
||||
result = someOperation()
|
||||
} finally {
|
||||
closeFile()
|
||||
}
|
||||
|
||||
result // should not error here
|
||||
|
||||
//// [flowAfterFinally1.js]
|
||||
var result;
|
||||
openFile();
|
||||
try {
|
||||
result = someOperation();
|
||||
}
|
||||
finally {
|
||||
closeFile();
|
||||
}
|
||||
result; // should not error here
|
29
tests/baselines/reference/flowAfterFinally1.symbols
Normal file
29
tests/baselines/reference/flowAfterFinally1.symbols
Normal file
|
@ -0,0 +1,29 @@
|
|||
=== tests/cases/compiler/flowAfterFinally1.ts ===
|
||||
declare function openFile(): void
|
||||
>openFile : Symbol(openFile, Decl(flowAfterFinally1.ts, 0, 0))
|
||||
|
||||
declare function closeFile(): void
|
||||
>closeFile : Symbol(closeFile, Decl(flowAfterFinally1.ts, 0, 33))
|
||||
|
||||
declare function someOperation(): {}
|
||||
>someOperation : Symbol(someOperation, Decl(flowAfterFinally1.ts, 1, 34))
|
||||
|
||||
var result: {}
|
||||
>result : Symbol(result, Decl(flowAfterFinally1.ts, 4, 3))
|
||||
|
||||
openFile()
|
||||
>openFile : Symbol(openFile, Decl(flowAfterFinally1.ts, 0, 0))
|
||||
|
||||
try {
|
||||
result = someOperation()
|
||||
>result : Symbol(result, Decl(flowAfterFinally1.ts, 4, 3))
|
||||
>someOperation : Symbol(someOperation, Decl(flowAfterFinally1.ts, 1, 34))
|
||||
|
||||
} finally {
|
||||
closeFile()
|
||||
>closeFile : Symbol(closeFile, Decl(flowAfterFinally1.ts, 0, 33))
|
||||
}
|
||||
|
||||
result // should not error here
|
||||
>result : Symbol(result, Decl(flowAfterFinally1.ts, 4, 3))
|
||||
|
33
tests/baselines/reference/flowAfterFinally1.types
Normal file
33
tests/baselines/reference/flowAfterFinally1.types
Normal file
|
@ -0,0 +1,33 @@
|
|||
=== tests/cases/compiler/flowAfterFinally1.ts ===
|
||||
declare function openFile(): void
|
||||
>openFile : () => void
|
||||
|
||||
declare function closeFile(): void
|
||||
>closeFile : () => void
|
||||
|
||||
declare function someOperation(): {}
|
||||
>someOperation : () => {}
|
||||
|
||||
var result: {}
|
||||
>result : {}
|
||||
|
||||
openFile()
|
||||
>openFile() : void
|
||||
>openFile : () => void
|
||||
|
||||
try {
|
||||
result = someOperation()
|
||||
>result = someOperation() : {}
|
||||
>result : {}
|
||||
>someOperation() : {}
|
||||
>someOperation : () => {}
|
||||
|
||||
} finally {
|
||||
closeFile()
|
||||
>closeFile() : void
|
||||
>closeFile : () => void
|
||||
}
|
||||
|
||||
result // should not error here
|
||||
>result : {}
|
||||
|
14
tests/baselines/reference/optionalParameterRetainsNull.js
Normal file
14
tests/baselines/reference/optionalParameterRetainsNull.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
//// [optionalParameterRetainsNull.ts]
|
||||
interface Bar { bar: number; foo: object | null; }
|
||||
|
||||
let a = {
|
||||
test<K extends keyof Bar> (a: K, b?: Bar[K] | null) { }
|
||||
};
|
||||
a.test("bar", null); // ok, null is assignable to number | null | undefined
|
||||
|
||||
|
||||
//// [optionalParameterRetainsNull.js]
|
||||
var a = {
|
||||
test: function (a, b) { }
|
||||
};
|
||||
a.test("bar", null); // ok, null is assignable to number | null | undefined
|
|
@ -0,0 +1,25 @@
|
|||
=== tests/cases/compiler/optionalParameterRetainsNull.ts ===
|
||||
interface Bar { bar: number; foo: object | null; }
|
||||
>Bar : Symbol(Bar, Decl(optionalParameterRetainsNull.ts, 0, 0))
|
||||
>bar : Symbol(Bar.bar, Decl(optionalParameterRetainsNull.ts, 0, 15))
|
||||
>foo : Symbol(Bar.foo, Decl(optionalParameterRetainsNull.ts, 0, 29))
|
||||
|
||||
let a = {
|
||||
>a : Symbol(a, Decl(optionalParameterRetainsNull.ts, 2, 3))
|
||||
|
||||
test<K extends keyof Bar> (a: K, b?: Bar[K] | null) { }
|
||||
>test : Symbol(test, Decl(optionalParameterRetainsNull.ts, 2, 9))
|
||||
>K : Symbol(K, Decl(optionalParameterRetainsNull.ts, 3, 7))
|
||||
>Bar : Symbol(Bar, Decl(optionalParameterRetainsNull.ts, 0, 0))
|
||||
>a : Symbol(a, Decl(optionalParameterRetainsNull.ts, 3, 29))
|
||||
>K : Symbol(K, Decl(optionalParameterRetainsNull.ts, 3, 7))
|
||||
>b : Symbol(b, Decl(optionalParameterRetainsNull.ts, 3, 34))
|
||||
>Bar : Symbol(Bar, Decl(optionalParameterRetainsNull.ts, 0, 0))
|
||||
>K : Symbol(K, Decl(optionalParameterRetainsNull.ts, 3, 7))
|
||||
|
||||
};
|
||||
a.test("bar", null); // ok, null is assignable to number | null | undefined
|
||||
>a.test : Symbol(test, Decl(optionalParameterRetainsNull.ts, 2, 9))
|
||||
>a : Symbol(a, Decl(optionalParameterRetainsNull.ts, 2, 3))
|
||||
>test : Symbol(test, Decl(optionalParameterRetainsNull.ts, 2, 9))
|
||||
|
31
tests/baselines/reference/optionalParameterRetainsNull.types
Normal file
31
tests/baselines/reference/optionalParameterRetainsNull.types
Normal file
|
@ -0,0 +1,31 @@
|
|||
=== tests/cases/compiler/optionalParameterRetainsNull.ts ===
|
||||
interface Bar { bar: number; foo: object | null; }
|
||||
>Bar : Bar
|
||||
>bar : number
|
||||
>foo : object | null
|
||||
>null : null
|
||||
|
||||
let a = {
|
||||
>a : { test<K extends "bar" | "foo">(a: K, b?: Bar[K] | null | undefined): void; }
|
||||
>{ test<K extends keyof Bar> (a: K, b?: Bar[K] | null) { }} : { test<K extends "bar" | "foo">(a: K, b?: Bar[K] | null | undefined): void; }
|
||||
|
||||
test<K extends keyof Bar> (a: K, b?: Bar[K] | null) { }
|
||||
>test : <K extends "bar" | "foo">(a: K, b?: Bar[K] | null | undefined) => void
|
||||
>K : K
|
||||
>Bar : Bar
|
||||
>a : K
|
||||
>K : K
|
||||
>b : Bar[K] | null | undefined
|
||||
>Bar : Bar
|
||||
>K : K
|
||||
>null : null
|
||||
|
||||
};
|
||||
a.test("bar", null); // ok, null is assignable to number | null | undefined
|
||||
>a.test("bar", null) : void
|
||||
>a.test : <K extends "bar" | "foo">(a: K, b?: Bar[K] | null | undefined) => void
|
||||
>a : { test<K extends "bar" | "foo">(a: K, b?: Bar[K] | null | undefined): void; }
|
||||
>test : <K extends "bar" | "foo">(a: K, b?: Bar[K] | null | undefined) => void
|
||||
>"bar" : "bar"
|
||||
>null : null
|
||||
|
|
@ -28,6 +28,7 @@ foo + bar + baz;
|
|||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var foo = require("foo");
|
||||
var bar = require("bar");
|
||||
var baz = require("baz");
|
||||
|
|
|
@ -16,3 +16,4 @@ import foo = require("foo");
|
|||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
|
|
|
@ -38,6 +38,7 @@ exports.__esModule = true;
|
|||
exports.l = 2;
|
||||
//// [index.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.m = 3;
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
// @strictNullChecks: true
|
||||
// @declaration: true
|
||||
function f(addUndefined1 = "J", addUndefined2?: number) {
|
||||
return addUndefined1.length + (addUndefined2 || 0);
|
||||
}
|
||||
function g(addUndefined = "J", addDefined: number) {
|
||||
return addUndefined.length + addDefined;
|
||||
}
|
||||
let total = f() + f('a', 1) + f('b') + f(undefined, 2);
|
||||
total = g('c', 3) + g(undefined, 4);
|
||||
|
||||
function foo1(x: string = "string", b: number) {
|
||||
x.length;
|
||||
}
|
||||
|
||||
function foo2(x = "string", b: number) {
|
||||
x.length; // ok, should be string
|
||||
}
|
||||
|
||||
function foo3(x: string | undefined = "string", b: number) {
|
||||
x.length; // ok, should be string
|
||||
}
|
||||
|
||||
function foo4(x: string | undefined = undefined, b: number) {
|
||||
x; // should be string | undefined
|
||||
}
|
||||
|
||||
|
||||
|
||||
// .d.ts should have `string | undefined` for foo1, foo2, foo3 and foo4
|
||||
foo1(undefined, 1);
|
||||
foo2(undefined, 1);
|
||||
foo3(undefined, 1);
|
||||
foo4(undefined, 1);
|
||||
|
||||
|
||||
function removeUndefinedButNotFalse(x = true) {
|
||||
if (x === false) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
declare const cond: boolean;
|
||||
function removeNothing(y = cond ? true : undefined) {
|
||||
if (y !== undefined) {
|
||||
if (y === false) {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
12
tests/cases/compiler/discriminatedUnionErrorMessage.ts
Normal file
12
tests/cases/compiler/discriminatedUnionErrorMessage.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
type Square = { kind: "sq", size: number }
|
||||
type Rectangle = { kind: "rt", x: number, y: number }
|
||||
type Circle = { kind: "cr", radius: number }
|
||||
type Shape =
|
||||
| Square
|
||||
| Rectangle
|
||||
| Circle;
|
||||
let shape: Shape = {
|
||||
kind: "sq",
|
||||
x: 12,
|
||||
y: 13,
|
||||
}
|
14
tests/cases/compiler/flowAfterFinally1.ts
Normal file
14
tests/cases/compiler/flowAfterFinally1.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
// @strictNullChecks: true
|
||||
declare function openFile(): void
|
||||
declare function closeFile(): void
|
||||
declare function someOperation(): {}
|
||||
|
||||
var result: {}
|
||||
openFile()
|
||||
try {
|
||||
result = someOperation()
|
||||
} finally {
|
||||
closeFile()
|
||||
}
|
||||
|
||||
result // should not error here
|
7
tests/cases/compiler/optionalParameterRetainsNull.ts
Normal file
7
tests/cases/compiler/optionalParameterRetainsNull.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
// @strictNullChecks: true
|
||||
interface Bar { bar: number; foo: object | null; }
|
||||
|
||||
let a = {
|
||||
test<K extends keyof Bar> (a: K, b?: Bar[K] | null) { }
|
||||
};
|
||||
a.test("bar", null); // ok, null is assignable to number | null | undefined
|
5
tests/cases/fourslash/quickInfoDisplayPartsIife.ts
Normal file
5
tests/cases/fourslash/quickInfoDisplayPartsIife.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
// @strictNullChecks: true
|
||||
////var iife = (function foo/*1*/(x, y) { return x })(12);
|
||||
|
||||
verify.quickInfoAt('1', '(local function) foo(x: number, y?: undefined): number');
|
Loading…
Reference in a new issue