Add strict property initialization checks

This commit is contained in:
Anders Hejlsberg
2017-11-16 10:36:32 -08:00
parent f1762a04ea
commit 5f6d7f34d8
2 changed files with 33 additions and 1 deletions
+29 -1
View File
@@ -11925,7 +11925,7 @@ namespace ts {
// on empty arrays are possible without implicit any errors and new element types can be inferred without
// type mismatch errors.
const resultType = getObjectFlags(evolvedType) & ObjectFlags.EvolvingArray && isEvolvingArrayOperationTarget(reference) ? anyArrayType : finalizeEvolvingArrayType(evolvedType);
if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) {
if (reference.parent && reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) {
return declaredType;
}
return resultType;
@@ -22072,6 +22072,7 @@ namespace ts {
if (produceDiagnostics) {
checkIndexConstraints(type);
checkTypeForDuplicateIndexSignatures(node);
checkPropertyInitialization(node);
}
}
@@ -22228,6 +22229,33 @@ namespace ts {
return ok;
}
function checkPropertyInitialization(node: ClassLikeDeclaration) {
if (!strictNullChecks || node.flags & NodeFlags.Ambient) {
return;
}
const constructor = findConstructorDeclaration(node);
for (const member of node.members) {
if (member.kind === SyntaxKind.PropertyDeclaration && !(<PropertyDeclaration>member).initializer) {
const propName = (<PropertyDeclaration>member).name;
if (isIdentifier(propName)) {
const type = getTypeOfSymbol(getSymbolOfNode(member));
if (!(type.flags & TypeFlags.Any || getFalsyFlags(type) & TypeFlags.Undefined)) {
if (!constructor || !isPropertyInitializedInConstructor(propName, type, constructor)) {
error(member.name, Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor, declarationNameToString(propName));
}
}
}
}
}
}
function isPropertyInitializedInConstructor(propName: Identifier, propType: Type, constructor: ConstructorDeclaration) {
const reference = createPropertyAccess(createThis(), propName);
reference.flowNode = constructor.returnFlowNode;
const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType));
return !(getFalsyFlags(flowType) & TypeFlags.Undefined);
}
function checkInterfaceDeclaration(node: InterfaceDeclaration) {
// Grammar checking
if (!checkGrammarDecoratorsAndModifiers(node)) checkGrammarInterfaceDeclaration(node);
+4
View File
@@ -1928,6 +1928,10 @@
"category": "Error",
"code": 2563
},
"Property '{0}' has no initializer and is not definitely assigned in the constructor.": {
"category": "Error",
"code": 2564
},
"JSX element attributes type '{0}' may not be a union type.": {
"category": "Error",
"code": 2600