Merge pull request #20166 from Microsoft/definiteAssignmentAssertions
Definite assignment assertions
This commit is contained in:
commit
9abb72d920
11 changed files with 711 additions and 9 deletions
|
@ -13123,8 +13123,10 @@ namespace ts {
|
|||
// the entire control flow graph from the variable's declaration (i.e. when the flow container and
|
||||
// declaration container are the same).
|
||||
const assumeInitialized = isParameter || isAlias || isOuterVariable ||
|
||||
type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || isInTypeQuery(node) || node.parent.kind === SyntaxKind.ExportSpecifier) ||
|
||||
type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & TypeFlags.Any) !== 0 ||
|
||||
isInTypeQuery(node) || node.parent.kind === SyntaxKind.ExportSpecifier) ||
|
||||
node.parent.kind === SyntaxKind.NonNullExpression ||
|
||||
declaration.kind === SyntaxKind.VariableDeclaration && (<VariableDeclaration>declaration).exclamationToken ||
|
||||
declaration.flags & NodeFlags.Ambient;
|
||||
const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, getRootDeclaration(declaration) as VariableLikeDeclaration) : type) :
|
||||
type === autoType || type === autoArrayType ? undefinedType :
|
||||
|
@ -22671,6 +22673,7 @@ namespace ts {
|
|||
function isInstancePropertyWithoutInitializer(node: Node) {
|
||||
return node.kind === SyntaxKind.PropertyDeclaration &&
|
||||
!hasModifier(node, ModifierFlags.Static | ModifierFlags.Abstract) &&
|
||||
!(<PropertyDeclaration>node).exclamationToken &&
|
||||
!(<PropertyDeclaration>node).initializer;
|
||||
}
|
||||
|
||||
|
@ -26103,6 +26106,10 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
if (node.exclamationToken && (node.parent.parent.kind !== SyntaxKind.VariableStatement || !node.type || node.initializer || node.flags & NodeFlags.Ambient)) {
|
||||
return grammarErrorOnNode(node.exclamationToken, Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context);
|
||||
}
|
||||
|
||||
if (compilerOptions.module !== ModuleKind.ES2015 && compilerOptions.module !== ModuleKind.ESNext && compilerOptions.module !== ModuleKind.System && !compilerOptions.noEmit &&
|
||||
!(node.parent.parent.flags & NodeFlags.Ambient) && hasModifier(node.parent.parent, ModifierFlags.Export)) {
|
||||
checkESModuleMarker(node.name);
|
||||
|
@ -26266,6 +26273,11 @@ namespace ts {
|
|||
if (node.flags & NodeFlags.Ambient && node.initializer) {
|
||||
return grammarErrorOnFirstToken(node.initializer, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts);
|
||||
}
|
||||
|
||||
if (node.exclamationToken && (!isClassLike(node.parent) || !node.type || node.initializer ||
|
||||
node.flags & NodeFlags.Ambient || hasModifier(node, ModifierFlags.Static | ModifierFlags.Abstract))) {
|
||||
return grammarErrorOnNode(node.exclamationToken, Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context);
|
||||
}
|
||||
}
|
||||
|
||||
function checkGrammarTopLevelElementForRequiredDeclareModifier(node: Node): boolean {
|
||||
|
|
|
@ -831,6 +831,10 @@
|
|||
"category": "Error",
|
||||
"code": 1254
|
||||
},
|
||||
"A definite assignment assertion '!' is not permitted in this context.": {
|
||||
"category": "Error",
|
||||
"code": 1255
|
||||
},
|
||||
"'with' statements are not allowed in an async function block.": {
|
||||
"category": "Error",
|
||||
"code": 1300
|
||||
|
|
|
@ -99,6 +99,7 @@ namespace ts {
|
|||
visitNode(cbNode, (<VariableLikeDeclaration>node).dotDotDotToken) ||
|
||||
visitNode(cbNode, (<VariableLikeDeclaration>node).name) ||
|
||||
visitNode(cbNode, (<VariableLikeDeclaration>node).questionToken) ||
|
||||
visitNode(cbNode, (<VariableLikeDeclaration>node).exclamationToken) ||
|
||||
visitNode(cbNode, (<VariableLikeDeclaration>node).type) ||
|
||||
visitNode(cbNode, (<VariableLikeDeclaration>node).initializer);
|
||||
case SyntaxKind.FunctionType:
|
||||
|
@ -5251,9 +5252,17 @@ namespace ts {
|
|||
return parseIdentifier();
|
||||
}
|
||||
|
||||
function parseVariableDeclaration(): VariableDeclaration {
|
||||
function parseVariableDeclarationAllowExclamation() {
|
||||
return parseVariableDeclaration(/*allowExclamation*/ true);
|
||||
}
|
||||
|
||||
function parseVariableDeclaration(allowExclamation?: boolean): VariableDeclaration {
|
||||
const node = <VariableDeclaration>createNode(SyntaxKind.VariableDeclaration);
|
||||
node.name = parseIdentifierOrPattern();
|
||||
if (allowExclamation && node.name.kind === SyntaxKind.Identifier &&
|
||||
token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
|
||||
node.exclamationToken = parseTokenNode();
|
||||
}
|
||||
node.type = parseTypeAnnotation();
|
||||
if (!isInOrOfKeyword(token())) {
|
||||
node.initializer = parseInitializer();
|
||||
|
@ -5295,7 +5304,8 @@ namespace ts {
|
|||
const savedDisallowIn = inDisallowInContext();
|
||||
setDisallowInContext(inForStatementInitializer);
|
||||
|
||||
node.declarations = parseDelimitedList(ParsingContext.VariableDeclarations, parseVariableDeclaration);
|
||||
node.declarations = parseDelimitedList(ParsingContext.VariableDeclarations,
|
||||
inForStatementInitializer ? parseVariableDeclaration : parseVariableDeclarationAllowExclamation);
|
||||
|
||||
setDisallowInContext(savedDisallowIn);
|
||||
}
|
||||
|
@ -5346,6 +5356,9 @@ namespace ts {
|
|||
|
||||
function parsePropertyDeclaration(node: PropertyDeclaration): PropertyDeclaration {
|
||||
node.kind = SyntaxKind.PropertyDeclaration;
|
||||
if (!node.questionToken && token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
|
||||
node.exclamationToken = parseTokenNode();
|
||||
}
|
||||
node.type = parseTypeAnnotation();
|
||||
|
||||
// For instance properties specifically, since they are evaluated inside the constructor,
|
||||
|
|
|
@ -598,6 +598,7 @@ namespace ts {
|
|||
|
||||
export type DotDotDotToken = Token<SyntaxKind.DotDotDotToken>;
|
||||
export type QuestionToken = Token<SyntaxKind.QuestionToken>;
|
||||
export type ExclamationToken = Token<SyntaxKind.ExclamationToken>;
|
||||
export type ColonToken = Token<SyntaxKind.ColonToken>;
|
||||
export type EqualsToken = Token<SyntaxKind.EqualsToken>;
|
||||
export type AsteriskToken = Token<SyntaxKind.AsteriskToken>;
|
||||
|
@ -762,6 +763,7 @@ namespace ts {
|
|||
kind: SyntaxKind.VariableDeclaration;
|
||||
parent?: VariableDeclarationList | CatchClause;
|
||||
name: BindingName; // Declared variable name
|
||||
exclamationToken?: ExclamationToken; // Optional definite assignment assertion
|
||||
type?: TypeNode; // Optional type annotation
|
||||
initializer?: Expression; // Optional initializer
|
||||
}
|
||||
|
@ -801,8 +803,9 @@ namespace ts {
|
|||
|
||||
export interface PropertyDeclaration extends ClassElement, JSDocContainer {
|
||||
kind: SyntaxKind.PropertyDeclaration;
|
||||
questionToken?: QuestionToken; // Present for use with reporting a grammar error
|
||||
name: PropertyName;
|
||||
questionToken?: QuestionToken; // Present for use with reporting a grammar error
|
||||
exclamationToken?: ExclamationToken;
|
||||
type?: TypeNode;
|
||||
initializer?: Expression; // Optional initializer
|
||||
}
|
||||
|
@ -860,6 +863,7 @@ namespace ts {
|
|||
dotDotDotToken?: DotDotDotToken;
|
||||
name: DeclarationName;
|
||||
questionToken?: QuestionToken;
|
||||
exclamationToken?: ExclamationToken;
|
||||
type?: TypeNode;
|
||||
initializer?: Expression;
|
||||
}
|
||||
|
|
|
@ -461,6 +461,7 @@ declare namespace ts {
|
|||
}
|
||||
type DotDotDotToken = Token<SyntaxKind.DotDotDotToken>;
|
||||
type QuestionToken = Token<SyntaxKind.QuestionToken>;
|
||||
type ExclamationToken = Token<SyntaxKind.ExclamationToken>;
|
||||
type ColonToken = Token<SyntaxKind.ColonToken>;
|
||||
type EqualsToken = Token<SyntaxKind.EqualsToken>;
|
||||
type AsteriskToken = Token<SyntaxKind.AsteriskToken>;
|
||||
|
@ -537,6 +538,7 @@ declare namespace ts {
|
|||
kind: SyntaxKind.VariableDeclaration;
|
||||
parent?: VariableDeclarationList | CatchClause;
|
||||
name: BindingName;
|
||||
exclamationToken?: ExclamationToken;
|
||||
type?: TypeNode;
|
||||
initializer?: Expression;
|
||||
}
|
||||
|
@ -571,8 +573,9 @@ declare namespace ts {
|
|||
}
|
||||
interface PropertyDeclaration extends ClassElement, JSDocContainer {
|
||||
kind: SyntaxKind.PropertyDeclaration;
|
||||
questionToken?: QuestionToken;
|
||||
name: PropertyName;
|
||||
questionToken?: QuestionToken;
|
||||
exclamationToken?: ExclamationToken;
|
||||
type?: TypeNode;
|
||||
initializer?: Expression;
|
||||
}
|
||||
|
@ -606,6 +609,7 @@ declare namespace ts {
|
|||
dotDotDotToken?: DotDotDotToken;
|
||||
name: DeclarationName;
|
||||
questionToken?: QuestionToken;
|
||||
exclamationToken?: ExclamationToken;
|
||||
type?: TypeNode;
|
||||
initializer?: Expression;
|
||||
}
|
||||
|
|
|
@ -461,6 +461,7 @@ declare namespace ts {
|
|||
}
|
||||
type DotDotDotToken = Token<SyntaxKind.DotDotDotToken>;
|
||||
type QuestionToken = Token<SyntaxKind.QuestionToken>;
|
||||
type ExclamationToken = Token<SyntaxKind.ExclamationToken>;
|
||||
type ColonToken = Token<SyntaxKind.ColonToken>;
|
||||
type EqualsToken = Token<SyntaxKind.EqualsToken>;
|
||||
type AsteriskToken = Token<SyntaxKind.AsteriskToken>;
|
||||
|
@ -537,6 +538,7 @@ declare namespace ts {
|
|||
kind: SyntaxKind.VariableDeclaration;
|
||||
parent?: VariableDeclarationList | CatchClause;
|
||||
name: BindingName;
|
||||
exclamationToken?: ExclamationToken;
|
||||
type?: TypeNode;
|
||||
initializer?: Expression;
|
||||
}
|
||||
|
@ -571,8 +573,9 @@ declare namespace ts {
|
|||
}
|
||||
interface PropertyDeclaration extends ClassElement, JSDocContainer {
|
||||
kind: SyntaxKind.PropertyDeclaration;
|
||||
questionToken?: QuestionToken;
|
||||
name: PropertyName;
|
||||
questionToken?: QuestionToken;
|
||||
exclamationToken?: ExclamationToken;
|
||||
type?: TypeNode;
|
||||
initializer?: Expression;
|
||||
}
|
||||
|
@ -606,6 +609,7 @@ declare namespace ts {
|
|||
dotDotDotToken?: DotDotDotToken;
|
||||
name: DeclarationName;
|
||||
questionToken?: QuestionToken;
|
||||
exclamationToken?: ExclamationToken;
|
||||
type?: TypeNode;
|
||||
initializer?: Expression;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(5,5): error TS2564: Property 'b' has no initializer and is not definitely assigned in the constructor.
|
||||
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(20,6): error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(21,6): error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(22,13): error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(28,6): error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(34,15): error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(68,10): error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(69,10): error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(70,10): error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(75,15): error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(76,15): error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
|
||||
|
||||
==== tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts (11 errors) ====
|
||||
// Suppress strict property initialization check
|
||||
|
||||
class C1 {
|
||||
a!: number;
|
||||
b: string; // Error
|
||||
~
|
||||
!!! error TS2564: Property 'b' has no initializer and is not definitely assigned in the constructor.
|
||||
}
|
||||
|
||||
// Suppress definite assignment check in constructor
|
||||
|
||||
class C2 {
|
||||
a!: number;
|
||||
constructor() {
|
||||
let x = this.a;
|
||||
}
|
||||
}
|
||||
|
||||
// Definite assignment assertion requires type annotation, no initializer, no static modifier
|
||||
|
||||
class C3 {
|
||||
a! = 1;
|
||||
~
|
||||
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
b!: number = 1;
|
||||
~
|
||||
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
static c!: number;
|
||||
~
|
||||
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
}
|
||||
|
||||
// Definite assignment assertion not permitted in ambient context
|
||||
|
||||
declare class C4 {
|
||||
a!: number;
|
||||
~
|
||||
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
}
|
||||
|
||||
// Definite assignment assertion not permitted on abstract property
|
||||
|
||||
abstract class C5 {
|
||||
abstract a!: number;
|
||||
~
|
||||
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
}
|
||||
|
||||
// Suppress definite assignment check for variable
|
||||
|
||||
function f1() {
|
||||
let x!: number;
|
||||
let y = x;
|
||||
var a!: number;
|
||||
var b = a;
|
||||
}
|
||||
|
||||
function f2() {
|
||||
let x!: string | number;
|
||||
if (typeof x === "string") {
|
||||
let s: string = x;
|
||||
}
|
||||
else {
|
||||
let n: number = x;
|
||||
}
|
||||
}
|
||||
|
||||
function f3() {
|
||||
let x!: number;
|
||||
const g = () => {
|
||||
x = 1;
|
||||
}
|
||||
g();
|
||||
let y = x;
|
||||
}
|
||||
|
||||
// Definite assignment assertion requires type annotation and no initializer
|
||||
|
||||
function f4() {
|
||||
let a!;
|
||||
~
|
||||
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
let b! = 1;
|
||||
~
|
||||
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
let c!: number = 1;
|
||||
~
|
||||
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
}
|
||||
|
||||
// Definite assignment assertion not permitted in ambient context
|
||||
|
||||
declare let v1!: number;
|
||||
~
|
||||
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
declare var v2!: number;
|
||||
~
|
||||
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
|
||||
|
166
tests/baselines/reference/definiteAssignmentAssertions.js
Normal file
166
tests/baselines/reference/definiteAssignmentAssertions.js
Normal file
|
@ -0,0 +1,166 @@
|
|||
//// [definiteAssignmentAssertions.ts]
|
||||
// Suppress strict property initialization check
|
||||
|
||||
class C1 {
|
||||
a!: number;
|
||||
b: string; // Error
|
||||
}
|
||||
|
||||
// Suppress definite assignment check in constructor
|
||||
|
||||
class C2 {
|
||||
a!: number;
|
||||
constructor() {
|
||||
let x = this.a;
|
||||
}
|
||||
}
|
||||
|
||||
// Definite assignment assertion requires type annotation, no initializer, no static modifier
|
||||
|
||||
class C3 {
|
||||
a! = 1;
|
||||
b!: number = 1;
|
||||
static c!: number;
|
||||
}
|
||||
|
||||
// Definite assignment assertion not permitted in ambient context
|
||||
|
||||
declare class C4 {
|
||||
a!: number;
|
||||
}
|
||||
|
||||
// Definite assignment assertion not permitted on abstract property
|
||||
|
||||
abstract class C5 {
|
||||
abstract a!: number;
|
||||
}
|
||||
|
||||
// Suppress definite assignment check for variable
|
||||
|
||||
function f1() {
|
||||
let x!: number;
|
||||
let y = x;
|
||||
var a!: number;
|
||||
var b = a;
|
||||
}
|
||||
|
||||
function f2() {
|
||||
let x!: string | number;
|
||||
if (typeof x === "string") {
|
||||
let s: string = x;
|
||||
}
|
||||
else {
|
||||
let n: number = x;
|
||||
}
|
||||
}
|
||||
|
||||
function f3() {
|
||||
let x!: number;
|
||||
const g = () => {
|
||||
x = 1;
|
||||
}
|
||||
g();
|
||||
let y = x;
|
||||
}
|
||||
|
||||
// Definite assignment assertion requires type annotation and no initializer
|
||||
|
||||
function f4() {
|
||||
let a!;
|
||||
let b! = 1;
|
||||
let c!: number = 1;
|
||||
}
|
||||
|
||||
// Definite assignment assertion not permitted in ambient context
|
||||
|
||||
declare let v1!: number;
|
||||
declare var v2!: number;
|
||||
|
||||
|
||||
//// [definiteAssignmentAssertions.js]
|
||||
"use strict";
|
||||
// Suppress strict property initialization check
|
||||
var C1 = /** @class */ (function () {
|
||||
function C1() {
|
||||
}
|
||||
return C1;
|
||||
}());
|
||||
// Suppress definite assignment check in constructor
|
||||
var C2 = /** @class */ (function () {
|
||||
function C2() {
|
||||
var x = this.a;
|
||||
}
|
||||
return C2;
|
||||
}());
|
||||
// Definite assignment assertion requires type annotation, no initializer, no static modifier
|
||||
var C3 = /** @class */ (function () {
|
||||
function C3() {
|
||||
this.a = 1;
|
||||
this.b = 1;
|
||||
}
|
||||
return C3;
|
||||
}());
|
||||
// Definite assignment assertion not permitted on abstract property
|
||||
var C5 = /** @class */ (function () {
|
||||
function C5() {
|
||||
}
|
||||
return C5;
|
||||
}());
|
||||
// Suppress definite assignment check for variable
|
||||
function f1() {
|
||||
var x;
|
||||
var y = x;
|
||||
var a;
|
||||
var b = a;
|
||||
}
|
||||
function f2() {
|
||||
var x;
|
||||
if (typeof x === "string") {
|
||||
var s = x;
|
||||
}
|
||||
else {
|
||||
var n = x;
|
||||
}
|
||||
}
|
||||
function f3() {
|
||||
var x;
|
||||
var g = function () {
|
||||
x = 1;
|
||||
};
|
||||
g();
|
||||
var y = x;
|
||||
}
|
||||
// Definite assignment assertion requires type annotation and no initializer
|
||||
function f4() {
|
||||
var a;
|
||||
var b = 1;
|
||||
var c = 1;
|
||||
}
|
||||
|
||||
|
||||
//// [definiteAssignmentAssertions.d.ts]
|
||||
declare class C1 {
|
||||
a: number;
|
||||
b: string;
|
||||
}
|
||||
declare class C2 {
|
||||
a: number;
|
||||
constructor();
|
||||
}
|
||||
declare class C3 {
|
||||
a: number;
|
||||
b: number;
|
||||
static c: number;
|
||||
}
|
||||
declare class C4 {
|
||||
a: number;
|
||||
}
|
||||
declare abstract class C5 {
|
||||
abstract a: number;
|
||||
}
|
||||
declare function f1(): void;
|
||||
declare function f2(): void;
|
||||
declare function f3(): void;
|
||||
declare function f4(): void;
|
||||
declare let v1: number;
|
||||
declare var v2: number;
|
146
tests/baselines/reference/definiteAssignmentAssertions.symbols
Normal file
146
tests/baselines/reference/definiteAssignmentAssertions.symbols
Normal file
|
@ -0,0 +1,146 @@
|
|||
=== tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts ===
|
||||
// Suppress strict property initialization check
|
||||
|
||||
class C1 {
|
||||
>C1 : Symbol(C1, Decl(definiteAssignmentAssertions.ts, 0, 0))
|
||||
|
||||
a!: number;
|
||||
>a : Symbol(C1.a, Decl(definiteAssignmentAssertions.ts, 2, 10))
|
||||
|
||||
b: string; // Error
|
||||
>b : Symbol(C1.b, Decl(definiteAssignmentAssertions.ts, 3, 15))
|
||||
}
|
||||
|
||||
// Suppress definite assignment check in constructor
|
||||
|
||||
class C2 {
|
||||
>C2 : Symbol(C2, Decl(definiteAssignmentAssertions.ts, 5, 1))
|
||||
|
||||
a!: number;
|
||||
>a : Symbol(C2.a, Decl(definiteAssignmentAssertions.ts, 9, 10))
|
||||
|
||||
constructor() {
|
||||
let x = this.a;
|
||||
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 12, 11))
|
||||
>this.a : Symbol(C2.a, Decl(definiteAssignmentAssertions.ts, 9, 10))
|
||||
>this : Symbol(C2, Decl(definiteAssignmentAssertions.ts, 5, 1))
|
||||
>a : Symbol(C2.a, Decl(definiteAssignmentAssertions.ts, 9, 10))
|
||||
}
|
||||
}
|
||||
|
||||
// Definite assignment assertion requires type annotation, no initializer, no static modifier
|
||||
|
||||
class C3 {
|
||||
>C3 : Symbol(C3, Decl(definiteAssignmentAssertions.ts, 14, 1))
|
||||
|
||||
a! = 1;
|
||||
>a : Symbol(C3.a, Decl(definiteAssignmentAssertions.ts, 18, 10))
|
||||
|
||||
b!: number = 1;
|
||||
>b : Symbol(C3.b, Decl(definiteAssignmentAssertions.ts, 19, 11))
|
||||
|
||||
static c!: number;
|
||||
>c : Symbol(C3.c, Decl(definiteAssignmentAssertions.ts, 20, 19))
|
||||
}
|
||||
|
||||
// Definite assignment assertion not permitted in ambient context
|
||||
|
||||
declare class C4 {
|
||||
>C4 : Symbol(C4, Decl(definiteAssignmentAssertions.ts, 22, 1))
|
||||
|
||||
a!: number;
|
||||
>a : Symbol(C4.a, Decl(definiteAssignmentAssertions.ts, 26, 18))
|
||||
}
|
||||
|
||||
// Definite assignment assertion not permitted on abstract property
|
||||
|
||||
abstract class C5 {
|
||||
>C5 : Symbol(C5, Decl(definiteAssignmentAssertions.ts, 28, 1))
|
||||
|
||||
abstract a!: number;
|
||||
>a : Symbol(C5.a, Decl(definiteAssignmentAssertions.ts, 32, 19))
|
||||
}
|
||||
|
||||
// Suppress definite assignment check for variable
|
||||
|
||||
function f1() {
|
||||
>f1 : Symbol(f1, Decl(definiteAssignmentAssertions.ts, 34, 1))
|
||||
|
||||
let x!: number;
|
||||
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 39, 7))
|
||||
|
||||
let y = x;
|
||||
>y : Symbol(y, Decl(definiteAssignmentAssertions.ts, 40, 7))
|
||||
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 39, 7))
|
||||
|
||||
var a!: number;
|
||||
>a : Symbol(a, Decl(definiteAssignmentAssertions.ts, 41, 7))
|
||||
|
||||
var b = a;
|
||||
>b : Symbol(b, Decl(definiteAssignmentAssertions.ts, 42, 7))
|
||||
>a : Symbol(a, Decl(definiteAssignmentAssertions.ts, 41, 7))
|
||||
}
|
||||
|
||||
function f2() {
|
||||
>f2 : Symbol(f2, Decl(definiteAssignmentAssertions.ts, 43, 1))
|
||||
|
||||
let x!: string | number;
|
||||
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 46, 7))
|
||||
|
||||
if (typeof x === "string") {
|
||||
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 46, 7))
|
||||
|
||||
let s: string = x;
|
||||
>s : Symbol(s, Decl(definiteAssignmentAssertions.ts, 48, 11))
|
||||
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 46, 7))
|
||||
}
|
||||
else {
|
||||
let n: number = x;
|
||||
>n : Symbol(n, Decl(definiteAssignmentAssertions.ts, 51, 11))
|
||||
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 46, 7))
|
||||
}
|
||||
}
|
||||
|
||||
function f3() {
|
||||
>f3 : Symbol(f3, Decl(definiteAssignmentAssertions.ts, 53, 1))
|
||||
|
||||
let x!: number;
|
||||
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 56, 7))
|
||||
|
||||
const g = () => {
|
||||
>g : Symbol(g, Decl(definiteAssignmentAssertions.ts, 57, 9))
|
||||
|
||||
x = 1;
|
||||
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 56, 7))
|
||||
}
|
||||
g();
|
||||
>g : Symbol(g, Decl(definiteAssignmentAssertions.ts, 57, 9))
|
||||
|
||||
let y = x;
|
||||
>y : Symbol(y, Decl(definiteAssignmentAssertions.ts, 61, 7))
|
||||
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 56, 7))
|
||||
}
|
||||
|
||||
// Definite assignment assertion requires type annotation and no initializer
|
||||
|
||||
function f4() {
|
||||
>f4 : Symbol(f4, Decl(definiteAssignmentAssertions.ts, 62, 1))
|
||||
|
||||
let a!;
|
||||
>a : Symbol(a, Decl(definiteAssignmentAssertions.ts, 67, 7))
|
||||
|
||||
let b! = 1;
|
||||
>b : Symbol(b, Decl(definiteAssignmentAssertions.ts, 68, 7))
|
||||
|
||||
let c!: number = 1;
|
||||
>c : Symbol(c, Decl(definiteAssignmentAssertions.ts, 69, 7))
|
||||
}
|
||||
|
||||
// Definite assignment assertion not permitted in ambient context
|
||||
|
||||
declare let v1!: number;
|
||||
>v1 : Symbol(v1, Decl(definiteAssignmentAssertions.ts, 74, 11))
|
||||
|
||||
declare var v2!: number;
|
||||
>v2 : Symbol(v2, Decl(definiteAssignmentAssertions.ts, 75, 11))
|
||||
|
157
tests/baselines/reference/definiteAssignmentAssertions.types
Normal file
157
tests/baselines/reference/definiteAssignmentAssertions.types
Normal file
|
@ -0,0 +1,157 @@
|
|||
=== tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts ===
|
||||
// Suppress strict property initialization check
|
||||
|
||||
class C1 {
|
||||
>C1 : C1
|
||||
|
||||
a!: number;
|
||||
>a : number
|
||||
|
||||
b: string; // Error
|
||||
>b : string
|
||||
}
|
||||
|
||||
// Suppress definite assignment check in constructor
|
||||
|
||||
class C2 {
|
||||
>C2 : C2
|
||||
|
||||
a!: number;
|
||||
>a : number
|
||||
|
||||
constructor() {
|
||||
let x = this.a;
|
||||
>x : number
|
||||
>this.a : number
|
||||
>this : this
|
||||
>a : number
|
||||
}
|
||||
}
|
||||
|
||||
// Definite assignment assertion requires type annotation, no initializer, no static modifier
|
||||
|
||||
class C3 {
|
||||
>C3 : C3
|
||||
|
||||
a! = 1;
|
||||
>a : number
|
||||
>1 : 1
|
||||
|
||||
b!: number = 1;
|
||||
>b : number
|
||||
>1 : 1
|
||||
|
||||
static c!: number;
|
||||
>c : number
|
||||
}
|
||||
|
||||
// Definite assignment assertion not permitted in ambient context
|
||||
|
||||
declare class C4 {
|
||||
>C4 : C4
|
||||
|
||||
a!: number;
|
||||
>a : number
|
||||
}
|
||||
|
||||
// Definite assignment assertion not permitted on abstract property
|
||||
|
||||
abstract class C5 {
|
||||
>C5 : C5
|
||||
|
||||
abstract a!: number;
|
||||
>a : number
|
||||
}
|
||||
|
||||
// Suppress definite assignment check for variable
|
||||
|
||||
function f1() {
|
||||
>f1 : () => void
|
||||
|
||||
let x!: number;
|
||||
>x : number
|
||||
|
||||
let y = x;
|
||||
>y : number
|
||||
>x : number
|
||||
|
||||
var a!: number;
|
||||
>a : number
|
||||
|
||||
var b = a;
|
||||
>b : number
|
||||
>a : number
|
||||
}
|
||||
|
||||
function f2() {
|
||||
>f2 : () => void
|
||||
|
||||
let x!: string | number;
|
||||
>x : string | number
|
||||
|
||||
if (typeof x === "string") {
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>x : string | number
|
||||
>"string" : "string"
|
||||
|
||||
let s: string = x;
|
||||
>s : string
|
||||
>x : string
|
||||
}
|
||||
else {
|
||||
let n: number = x;
|
||||
>n : number
|
||||
>x : number
|
||||
}
|
||||
}
|
||||
|
||||
function f3() {
|
||||
>f3 : () => void
|
||||
|
||||
let x!: number;
|
||||
>x : number
|
||||
|
||||
const g = () => {
|
||||
>g : () => void
|
||||
>() => { x = 1; } : () => void
|
||||
|
||||
x = 1;
|
||||
>x = 1 : 1
|
||||
>x : number
|
||||
>1 : 1
|
||||
}
|
||||
g();
|
||||
>g() : void
|
||||
>g : () => void
|
||||
|
||||
let y = x;
|
||||
>y : number
|
||||
>x : number
|
||||
}
|
||||
|
||||
// Definite assignment assertion requires type annotation and no initializer
|
||||
|
||||
function f4() {
|
||||
>f4 : () => void
|
||||
|
||||
let a!;
|
||||
>a : any
|
||||
|
||||
let b! = 1;
|
||||
>b : number
|
||||
>1 : 1
|
||||
|
||||
let c!: number = 1;
|
||||
>c : number
|
||||
>1 : 1
|
||||
}
|
||||
|
||||
// Definite assignment assertion not permitted in ambient context
|
||||
|
||||
declare let v1!: number;
|
||||
>v1 : number
|
||||
|
||||
declare var v2!: number;
|
||||
>v2 : number
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
// @strict: true
|
||||
// @declaration: true
|
||||
|
||||
// Suppress strict property initialization check
|
||||
|
||||
class C1 {
|
||||
a!: number;
|
||||
b: string; // Error
|
||||
}
|
||||
|
||||
// Suppress definite assignment check in constructor
|
||||
|
||||
class C2 {
|
||||
a!: number;
|
||||
constructor() {
|
||||
let x = this.a;
|
||||
}
|
||||
}
|
||||
|
||||
// Definite assignment assertion requires type annotation, no initializer, no static modifier
|
||||
|
||||
class C3 {
|
||||
a! = 1;
|
||||
b!: number = 1;
|
||||
static c!: number;
|
||||
}
|
||||
|
||||
// Definite assignment assertion not permitted in ambient context
|
||||
|
||||
declare class C4 {
|
||||
a!: number;
|
||||
}
|
||||
|
||||
// Definite assignment assertion not permitted on abstract property
|
||||
|
||||
abstract class C5 {
|
||||
abstract a!: number;
|
||||
}
|
||||
|
||||
// Suppress definite assignment check for variable
|
||||
|
||||
function f1() {
|
||||
let x!: number;
|
||||
let y = x;
|
||||
var a!: number;
|
||||
var b = a;
|
||||
}
|
||||
|
||||
function f2() {
|
||||
let x!: string | number;
|
||||
if (typeof x === "string") {
|
||||
let s: string = x;
|
||||
}
|
||||
else {
|
||||
let n: number = x;
|
||||
}
|
||||
}
|
||||
|
||||
function f3() {
|
||||
let x!: number;
|
||||
const g = () => {
|
||||
x = 1;
|
||||
}
|
||||
g();
|
||||
let y = x;
|
||||
}
|
||||
|
||||
// Definite assignment assertion requires type annotation and no initializer
|
||||
|
||||
function f4() {
|
||||
let a!;
|
||||
let b! = 1;
|
||||
let c!: number = 1;
|
||||
}
|
||||
|
||||
// Definite assignment assertion not permitted in ambient context
|
||||
|
||||
declare let v1!: number;
|
||||
declare var v2!: number;
|
Loading…
Reference in a new issue