fix(compiler-cli): allow '==' to compare nullable types (#16731)
Fixes: #16729 * fix(compiler-cli): diagnose issues in conditional of ternary Fixes: #16730
This commit is contained in:
parent
c805082648
commit
d761059e4d
|
@ -51,8 +51,29 @@ export class AstType implements AstVisitor {
|
|||
return kind;
|
||||
}
|
||||
|
||||
const leftType = this.getType(ast.left);
|
||||
const rightType = this.getType(ast.right);
|
||||
const getType = (ast: AST, operation: string): Symbol => {
|
||||
const type = this.getType(ast);
|
||||
if (type.nullable) {
|
||||
switch (operation) {
|
||||
case '&&':
|
||||
case '||':
|
||||
case '==':
|
||||
case '!=':
|
||||
case '===':
|
||||
case '!==':
|
||||
// Nullable allowed.
|
||||
break;
|
||||
default:
|
||||
this.reportError(`The expression might be null`, ast);
|
||||
break;
|
||||
}
|
||||
return this.query.getNonNullableType(type);
|
||||
}
|
||||
return type;
|
||||
};
|
||||
|
||||
const leftType = getType(ast.left, ast.operation);
|
||||
const rightType = getType(ast.right, ast.operation);
|
||||
const leftRawKind = this.query.getTypeKind(leftType);
|
||||
const rightRawKind = this.query.getTypeKind(rightType);
|
||||
const leftKind = normalize(leftRawKind, rightRawKind);
|
||||
|
@ -166,6 +187,9 @@ export class AstType implements AstVisitor {
|
|||
|
||||
visitConditional(ast: Conditional) {
|
||||
// The type of a conditional is the union of the true and false conditions.
|
||||
if (this.diagnostics) {
|
||||
visitAstChildren(ast, this);
|
||||
}
|
||||
return this.query.getTypeUnion(this.getType(ast.trueExp), this.getType(ast.falseExp));
|
||||
}
|
||||
|
||||
|
|
|
@ -175,7 +175,16 @@ describe('expression diagnostics', () => {
|
|||
it('should reject an uncalled event handler',
|
||||
() => reject(
|
||||
'<div (click)="click">{{person.name.first}}</div>', 'Unexpected callable expression'));
|
||||
|
||||
describe('with comparisions between nullable and non-nullable', () => {
|
||||
it('should accept ==', () => accept(`<div>{{e == 1 ? 'a' : 'b'}}</div>`));
|
||||
it('should accept ===', () => accept(`<div>{{e === 1 ? 'a' : 'b'}}</div>`));
|
||||
it('should accept !=', () => accept(`<div>{{e != 1 ? 'a' : 'b'}}</div>`));
|
||||
it('should accept !==', () => accept(`<div>{{e !== 1 ? 'a' : 'b'}}</div>`));
|
||||
it('should accept &&', () => accept(`<div>{{e && 1 ? 'a' : 'b'}}</div>`));
|
||||
it('should accept ||', () => accept(`<div>{{e || 1 ? 'a' : 'b'}}</div>`));
|
||||
it('should reject >',
|
||||
() => reject(`<div>{{e > 1 ? 'a' : 'b'}}</div>`, 'The expression might be null'));
|
||||
});
|
||||
});
|
||||
|
||||
const FILES: Directory = {
|
||||
|
@ -216,6 +225,7 @@ const FILES: Directory = {
|
|||
promised_people: Promise<Person[]>;
|
||||
private private_person: Person;
|
||||
private private_people: Person[];
|
||||
e?: number;
|
||||
|
||||
getPerson(): Person { return this.person; }
|
||||
click() {}
|
||||
|
|
Loading…
Reference in New Issue