mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Add related diagnostic to "used before defined" if type is a function that returns a union with undefined (#33171)
* Add "use before defined" diagnostic * Make "use before defined" diagnostic as related information to TS2454 * Add baseline tests for "use before defined" * Add test for type alias union with undefined for "use before defined" diagnostic * Update baselines
This commit is contained in:
parent
47ec514cf4
commit
be960fa356
@ -20190,7 +20190,26 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else if (!assumeInitialized && !(getFalsyFlags(type) & TypeFlags.Undefined) && getFalsyFlags(flowType) & TypeFlags.Undefined) {
|
||||
error(node, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol));
|
||||
const diag = error(node, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol));
|
||||
|
||||
// See GH:32846 - if the user is using a variable whose type is () => T1 | ... | undefined
|
||||
// they may have meant to specify the type as (() => T1 | ...) | undefined
|
||||
// This is assumed if: the type is a FunctionType, the return type is a Union, the last constituent of
|
||||
// the union is `undefined`
|
||||
if (type.symbol && type.symbol.declarations.length === 1 && isFunctionTypeNode(type.symbol.declarations[0])) {
|
||||
const funcTypeNode = <FunctionTypeNode>type.symbol.declarations[0];
|
||||
const returnType = getReturnTypeFromAnnotation(funcTypeNode);
|
||||
if (returnType && returnType.flags & TypeFlags.Union) {
|
||||
const unionTypes = (<UnionTypeNode>funcTypeNode.type).types;
|
||||
if (unionTypes && unionTypes[unionTypes.length - 1].kind === SyntaxKind.UndefinedKeyword) {
|
||||
const parenedFuncType = getMutableClone(funcTypeNode);
|
||||
// Highlight to the end of the second to last constituent of the union
|
||||
parenedFuncType.end = unionTypes[unionTypes.length - 2].end;
|
||||
addRelatedInfo(diag, createDiagnosticForNode(parenedFuncType, Diagnostics.Did_you_mean_to_parenthesize_this_function_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the declared type to reduce follow-on errors
|
||||
return type;
|
||||
}
|
||||
|
||||
@ -1047,6 +1047,10 @@
|
||||
"category": "Error",
|
||||
"code": 1359
|
||||
},
|
||||
"Did you mean to parenthesize this function type?": {
|
||||
"category": "Error",
|
||||
"code": 1360
|
||||
},
|
||||
|
||||
"The types of '{0}' are incompatible between these types.": {
|
||||
"category": "Error",
|
||||
|
||||
@ -0,0 +1,74 @@
|
||||
tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts(2,1): error TS2454: Variable 'a' is used before being assigned.
|
||||
tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts(6,1): error TS2454: Variable 'c' is used before being assigned.
|
||||
tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts(10,1): error TS2454: Variable 'd' is used before being assigned.
|
||||
tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts(13,1): error TS2454: Variable 'e' is used before being assigned.
|
||||
tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts(16,1): error TS2454: Variable 'f' is used before being assigned.
|
||||
tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts(19,1): error TS2454: Variable 'g' is used before being assigned.
|
||||
tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts(24,1): error TS2454: Variable 'h' is used before being assigned.
|
||||
tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts(28,1): error TS2454: Variable 'i' is used before being assigned.
|
||||
tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts(32,1): error TS2454: Variable 'j' is used before being assigned.
|
||||
tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts(36,1): error TS2454: Variable 'j' is used before being assigned.
|
||||
|
||||
|
||||
==== tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts (10 errors) ====
|
||||
let a: () => void | undefined;
|
||||
a; // Error did you mean to paren this function type
|
||||
~
|
||||
!!! error TS2454: Variable 'a' is used before being assigned.
|
||||
!!! related TS1360 tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts:1:8: Did you mean to parenthesize this function type?
|
||||
|
||||
function b (): void | undefined {}
|
||||
let c: typeof b;
|
||||
c;
|
||||
~
|
||||
!!! error TS2454: Variable 'c' is used before being assigned.
|
||||
|
||||
type Undefined = undefined
|
||||
let d: () => void | Undefined;
|
||||
d;
|
||||
~
|
||||
!!! error TS2454: Variable 'd' is used before being assigned.
|
||||
|
||||
let e: () => string | void | number | object | undefined;
|
||||
e; // Error did you mean to paren...
|
||||
~
|
||||
!!! error TS2454: Variable 'e' is used before being assigned.
|
||||
!!! related TS1360 tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts:12:8: Did you mean to parenthesize this function type?
|
||||
|
||||
let f: () => void;
|
||||
f;
|
||||
~
|
||||
!!! error TS2454: Variable 'f' is used before being assigned.
|
||||
|
||||
let g: () => undefined;
|
||||
g;
|
||||
~
|
||||
!!! error TS2454: Variable 'g' is used before being assigned.
|
||||
|
||||
type T1 = undefined | string;
|
||||
type T2 = undefined | void;
|
||||
let h: () => T1 & T2;
|
||||
h;
|
||||
~
|
||||
!!! error TS2454: Variable 'h' is used before being assigned.
|
||||
|
||||
type T3 = void | undefined;
|
||||
let i: () => T3;
|
||||
i;
|
||||
~
|
||||
!!! error TS2454: Variable 'i' is used before being assigned.
|
||||
|
||||
type T4 = () => void | undefined;
|
||||
let j: T4;
|
||||
j; // Error did you mean to paren...
|
||||
~
|
||||
!!! error TS2454: Variable 'j' is used before being assigned.
|
||||
!!! related TS1360 tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts:30:11: Did you mean to parenthesize this function type?
|
||||
|
||||
type T5 = () => void
|
||||
let k: T5 | undefined
|
||||
j;
|
||||
~
|
||||
!!! error TS2454: Variable 'j' is used before being assigned.
|
||||
!!! related TS1360 tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts:30:11: Did you mean to parenthesize this function type?
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
//// [functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts]
|
||||
let a: () => void | undefined;
|
||||
a; // Error did you mean to paren this function type
|
||||
|
||||
function b (): void | undefined {}
|
||||
let c: typeof b;
|
||||
c;
|
||||
|
||||
type Undefined = undefined
|
||||
let d: () => void | Undefined;
|
||||
d;
|
||||
|
||||
let e: () => string | void | number | object | undefined;
|
||||
e; // Error did you mean to paren...
|
||||
|
||||
let f: () => void;
|
||||
f;
|
||||
|
||||
let g: () => undefined;
|
||||
g;
|
||||
|
||||
type T1 = undefined | string;
|
||||
type T2 = undefined | void;
|
||||
let h: () => T1 & T2;
|
||||
h;
|
||||
|
||||
type T3 = void | undefined;
|
||||
let i: () => T3;
|
||||
i;
|
||||
|
||||
type T4 = () => void | undefined;
|
||||
let j: T4;
|
||||
j; // Error did you mean to paren...
|
||||
|
||||
type T5 = () => void
|
||||
let k: T5 | undefined
|
||||
j;
|
||||
|
||||
|
||||
//// [functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.js]
|
||||
var a;
|
||||
a; // Error did you mean to paren this function type
|
||||
function b() { }
|
||||
var c;
|
||||
c;
|
||||
var d;
|
||||
d;
|
||||
var e;
|
||||
e; // Error did you mean to paren...
|
||||
var f;
|
||||
f;
|
||||
var g;
|
||||
g;
|
||||
var h;
|
||||
h;
|
||||
var i;
|
||||
i;
|
||||
var j;
|
||||
j; // Error did you mean to paren...
|
||||
var k;
|
||||
j;
|
||||
@ -0,0 +1,89 @@
|
||||
=== tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts ===
|
||||
let a: () => void | undefined;
|
||||
>a : Symbol(a, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 0, 3))
|
||||
|
||||
a; // Error did you mean to paren this function type
|
||||
>a : Symbol(a, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 0, 3))
|
||||
|
||||
function b (): void | undefined {}
|
||||
>b : Symbol(b, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 1, 2))
|
||||
|
||||
let c: typeof b;
|
||||
>c : Symbol(c, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 4, 3))
|
||||
>b : Symbol(b, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 1, 2))
|
||||
|
||||
c;
|
||||
>c : Symbol(c, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 4, 3))
|
||||
|
||||
type Undefined = undefined
|
||||
>Undefined : Symbol(Undefined, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 5, 2))
|
||||
|
||||
let d: () => void | Undefined;
|
||||
>d : Symbol(d, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 8, 3))
|
||||
>Undefined : Symbol(Undefined, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 5, 2))
|
||||
|
||||
d;
|
||||
>d : Symbol(d, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 8, 3))
|
||||
|
||||
let e: () => string | void | number | object | undefined;
|
||||
>e : Symbol(e, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 11, 3))
|
||||
|
||||
e; // Error did you mean to paren...
|
||||
>e : Symbol(e, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 11, 3))
|
||||
|
||||
let f: () => void;
|
||||
>f : Symbol(f, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 14, 3))
|
||||
|
||||
f;
|
||||
>f : Symbol(f, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 14, 3))
|
||||
|
||||
let g: () => undefined;
|
||||
>g : Symbol(g, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 17, 3))
|
||||
|
||||
g;
|
||||
>g : Symbol(g, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 17, 3))
|
||||
|
||||
type T1 = undefined | string;
|
||||
>T1 : Symbol(T1, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 18, 2))
|
||||
|
||||
type T2 = undefined | void;
|
||||
>T2 : Symbol(T2, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 20, 29))
|
||||
|
||||
let h: () => T1 & T2;
|
||||
>h : Symbol(h, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 22, 3))
|
||||
>T1 : Symbol(T1, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 18, 2))
|
||||
>T2 : Symbol(T2, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 20, 29))
|
||||
|
||||
h;
|
||||
>h : Symbol(h, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 22, 3))
|
||||
|
||||
type T3 = void | undefined;
|
||||
>T3 : Symbol(T3, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 23, 2))
|
||||
|
||||
let i: () => T3;
|
||||
>i : Symbol(i, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 26, 3))
|
||||
>T3 : Symbol(T3, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 23, 2))
|
||||
|
||||
i;
|
||||
>i : Symbol(i, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 26, 3))
|
||||
|
||||
type T4 = () => void | undefined;
|
||||
>T4 : Symbol(T4, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 27, 2))
|
||||
|
||||
let j: T4;
|
||||
>j : Symbol(j, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 30, 3))
|
||||
>T4 : Symbol(T4, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 27, 2))
|
||||
|
||||
j; // Error did you mean to paren...
|
||||
>j : Symbol(j, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 30, 3))
|
||||
|
||||
type T5 = () => void
|
||||
>T5 : Symbol(T5, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 31, 2))
|
||||
|
||||
let k: T5 | undefined
|
||||
>k : Symbol(k, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 34, 3))
|
||||
>T5 : Symbol(T5, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 31, 2))
|
||||
|
||||
j;
|
||||
>j : Symbol(j, Decl(functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts, 30, 3))
|
||||
|
||||
@ -0,0 +1,83 @@
|
||||
=== tests/cases/compiler/functionTypeReturnsUnionWithUndefinedWithStrictNullChecks.ts ===
|
||||
let a: () => void | undefined;
|
||||
>a : () => void | undefined
|
||||
|
||||
a; // Error did you mean to paren this function type
|
||||
>a : () => void | undefined
|
||||
|
||||
function b (): void | undefined {}
|
||||
>b : () => void | undefined
|
||||
|
||||
let c: typeof b;
|
||||
>c : () => void | undefined
|
||||
>b : () => void | undefined
|
||||
|
||||
c;
|
||||
>c : () => void | undefined
|
||||
|
||||
type Undefined = undefined
|
||||
>Undefined : undefined
|
||||
|
||||
let d: () => void | Undefined;
|
||||
>d : () => void | undefined
|
||||
|
||||
d;
|
||||
>d : () => void | undefined
|
||||
|
||||
let e: () => string | void | number | object | undefined;
|
||||
>e : () => string | number | void | object | undefined
|
||||
|
||||
e; // Error did you mean to paren...
|
||||
>e : () => string | number | void | object | undefined
|
||||
|
||||
let f: () => void;
|
||||
>f : () => void
|
||||
|
||||
f;
|
||||
>f : () => void
|
||||
|
||||
let g: () => undefined;
|
||||
>g : () => undefined
|
||||
|
||||
g;
|
||||
>g : () => undefined
|
||||
|
||||
type T1 = undefined | string;
|
||||
>T1 : T1
|
||||
|
||||
type T2 = undefined | void;
|
||||
>T2 : void | undefined
|
||||
|
||||
let h: () => T1 & T2;
|
||||
>h : () => undefined
|
||||
|
||||
h;
|
||||
>h : () => undefined
|
||||
|
||||
type T3 = void | undefined;
|
||||
>T3 : void | undefined
|
||||
|
||||
let i: () => T3;
|
||||
>i : () => void | undefined
|
||||
|
||||
i;
|
||||
>i : () => void | undefined
|
||||
|
||||
type T4 = () => void | undefined;
|
||||
>T4 : T4
|
||||
|
||||
let j: T4;
|
||||
>j : T4
|
||||
|
||||
j; // Error did you mean to paren...
|
||||
>j : T4
|
||||
|
||||
type T5 = () => void
|
||||
>T5 : T5
|
||||
|
||||
let k: T5 | undefined
|
||||
>k : T5 | undefined
|
||||
|
||||
j;
|
||||
>j : T4
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
// @strictNullChecks: true
|
||||
|
||||
let a: () => void | undefined;
|
||||
a; // Error did you mean to paren this function type
|
||||
|
||||
function b (): void | undefined {}
|
||||
let c: typeof b;
|
||||
c;
|
||||
|
||||
type Undefined = undefined
|
||||
let d: () => void | Undefined;
|
||||
d;
|
||||
|
||||
let e: () => string | void | number | object | undefined;
|
||||
e; // Error did you mean to paren...
|
||||
|
||||
let f: () => void;
|
||||
f;
|
||||
|
||||
let g: () => undefined;
|
||||
g;
|
||||
|
||||
type T1 = undefined | string;
|
||||
type T2 = undefined | void;
|
||||
let h: () => T1 & T2;
|
||||
h;
|
||||
|
||||
type T3 = void | undefined;
|
||||
let i: () => T3;
|
||||
i;
|
||||
|
||||
type T4 = () => void | undefined;
|
||||
let j: T4;
|
||||
j; // Error did you mean to paren...
|
||||
|
||||
type T5 = () => void
|
||||
let k: T5 | undefined
|
||||
j;
|
||||
Loading…
x
Reference in New Issue
Block a user