mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-11 10:00:13 -06:00
Implement constructor type guard (#32774)
* Implement constructor type guard * Fix code review issues for constructor type guard. - Do not limit constructor expression to only identifiers - Fix `assumeTrue` and operator no-narrow check - Use better way to check that identifier type is a function - Loosen restriction on what expr is left of ".constructor" - Update typeGuardConstructorClassAndNumber test to include else cases * Fix grammar & spacing in `narrowTypeByConstructor` * fix bad merge * switch (back?) to crlf * update baselines Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com>
This commit is contained in:
parent
b78ef30cb7
commit
ae3d28b5eb
@ -20147,6 +20147,12 @@ namespace ts {
|
||||
if (right.kind === SyntaxKind.TypeOfExpression && isStringLiteralLike(left)) {
|
||||
return narrowTypeByTypeof(type, <TypeOfExpression>right, operator, left, assumeTrue);
|
||||
}
|
||||
if (isConstructorAccessExpression(left)) {
|
||||
return narrowTypeByConstructor(type, left, operator, right, assumeTrue);
|
||||
}
|
||||
if (isConstructorAccessExpression(right)) {
|
||||
return narrowTypeByConstructor(type, right, operator, left, assumeTrue);
|
||||
}
|
||||
if (isMatchingReference(reference, left)) {
|
||||
return narrowTypeByEquality(type, operator, right, assumeTrue);
|
||||
}
|
||||
@ -20432,6 +20438,59 @@ namespace ts {
|
||||
return getTypeWithFacts(mapType(type, narrowTypeForTypeofSwitch(impliedType)), switchFacts);
|
||||
}
|
||||
|
||||
function narrowTypeByConstructor(type: Type, constructorAccessExpr: AccessExpression, operator: SyntaxKind, identifier: Expression, assumeTrue: boolean): Type {
|
||||
// Do not narrow when checking inequality.
|
||||
if (assumeTrue ? (operator !== SyntaxKind.EqualsEqualsToken && operator !== SyntaxKind.EqualsEqualsEqualsToken) : (operator !== SyntaxKind.ExclamationEqualsToken && operator !== SyntaxKind.ExclamationEqualsEqualsToken)) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// In the case of `x.y`, a `x.constructor === T` type guard resets the narrowed type of `y` to its declared type.
|
||||
if (!isMatchingReference(reference, constructorAccessExpr.expression)) {
|
||||
return declaredType;
|
||||
}
|
||||
|
||||
// Get the type of the constructor identifier expression, if it is not a function then do not narrow.
|
||||
const identifierType = getTypeOfExpression(identifier);
|
||||
if (!isFunctionType(identifierType) && !isConstructorType(identifierType)) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// Get the prototype property of the type identifier so we can find out its type.
|
||||
const prototypeProperty = getPropertyOfType(identifierType, "prototype" as __String);
|
||||
if (!prototypeProperty) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// Get the type of the prototype, if it is undefined, or the global `Object` or `Function` types then do not narrow.
|
||||
const prototypeType = getTypeOfSymbol(prototypeProperty);
|
||||
const candidate = !isTypeAny(prototypeType) ? prototypeType : undefined;
|
||||
if (!candidate || candidate === globalObjectType || candidate === globalFunctionType) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// If the type that is being narrowed is `any` then just return the `candidate` type since every type is a subtype of `any`.
|
||||
if (isTypeAny(type)) {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
// Filter out types that are not considered to be "constructed by" the `candidate` type.
|
||||
return filterType(type, t => isConstructedBy(t, candidate));
|
||||
|
||||
function isConstructedBy(source: Type, target: Type) {
|
||||
// If either the source or target type are a class type then we need to check that they are the same exact type.
|
||||
// This is because you may have a class `A` that defines some set of properties, and another class `B`
|
||||
// that defines the same set of properties as class `A`, in that case they are structurally the same
|
||||
// type, but when you do something like `instanceOfA.constructor === B` it will return false.
|
||||
if (source.flags & TypeFlags.Object && getObjectFlags(source) & ObjectFlags.Class ||
|
||||
target.flags & TypeFlags.Object && getObjectFlags(target) & ObjectFlags.Class) {
|
||||
return source.symbol === target.symbol;
|
||||
}
|
||||
|
||||
// For all other types just check that the `source` type is a subtype of the `target` type.
|
||||
return isTypeSubtypeOf(source, target);
|
||||
}
|
||||
}
|
||||
|
||||
function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
|
||||
const left = getReferenceCandidate(expr.left);
|
||||
if (!isMatchingReference(reference, left)) {
|
||||
|
||||
@ -4426,6 +4426,13 @@ namespace ts {
|
||||
return isPropertyAccessExpression(node) && isEntityNameExpression(node.expression);
|
||||
}
|
||||
|
||||
export function isConstructorAccessExpression(expr: Expression): expr is AccessExpression {
|
||||
return (
|
||||
isPropertyAccessExpression(expr) && idText(expr.name) === "constructor" ||
|
||||
isElementAccessExpression(expr) && isStringLiteralLike(expr.argumentExpression) && expr.argumentExpression.text === "constructor"
|
||||
);
|
||||
}
|
||||
|
||||
export function tryGetPropertyAccessOrIdentifierToString(expr: Expression): string | undefined {
|
||||
if (isPropertyAccessExpression(expr)) {
|
||||
const baseStr = tryGetPropertyAccessOrIdentifierToString(expr.expression);
|
||||
|
||||
@ -0,0 +1,163 @@
|
||||
tests/cases/compiler/typeGuardConstructorClassAndNumber.ts(66,10): error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
Property 'property1' does not exist on type 'number'.
|
||||
tests/cases/compiler/typeGuardConstructorClassAndNumber.ts(73,10): error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
Property 'property1' does not exist on type 'number'.
|
||||
tests/cases/compiler/typeGuardConstructorClassAndNumber.ts(80,10): error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
Property 'property1' does not exist on type 'number'.
|
||||
tests/cases/compiler/typeGuardConstructorClassAndNumber.ts(87,10): error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
Property 'property1' does not exist on type 'number'.
|
||||
tests/cases/compiler/typeGuardConstructorClassAndNumber.ts(94,10): error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
Property 'property1' does not exist on type 'number'.
|
||||
tests/cases/compiler/typeGuardConstructorClassAndNumber.ts(101,10): error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
Property 'property1' does not exist on type 'number'.
|
||||
tests/cases/compiler/typeGuardConstructorClassAndNumber.ts(108,10): error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
Property 'property1' does not exist on type 'number'.
|
||||
tests/cases/compiler/typeGuardConstructorClassAndNumber.ts(115,10): error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
Property 'property1' does not exist on type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/typeGuardConstructorClassAndNumber.ts (8 errors) ====
|
||||
// Typical case
|
||||
class C1 {
|
||||
property1: string;
|
||||
}
|
||||
|
||||
let var1: C1 | number;
|
||||
if (var1.constructor == C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (var1["constructor"] == C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (var1.constructor === C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (var1["constructor"] === C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 == var1.constructor) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 == var1["constructor"]) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 === var1.constructor) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 === var1["constructor"]) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
|
||||
if (var1.constructor != C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
~~~~~~~~~
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number'.
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (var1["constructor"] != C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
~~~~~~~~~
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number'.
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (var1.constructor !== C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
~~~~~~~~~
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number'.
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (var1["constructor"] !== C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
~~~~~~~~~
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number'.
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 != var1.constructor) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
~~~~~~~~~
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number'.
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 != var1["constructor"]) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
~~~~~~~~~
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number'.
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 !== var1.constructor) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
~~~~~~~~~
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number'.
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 !== var1["constructor"]) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
~~~~~~~~~
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number | C1'.
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'number'.
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
|
||||
242
tests/baselines/reference/typeGuardConstructorClassAndNumber.js
Normal file
242
tests/baselines/reference/typeGuardConstructorClassAndNumber.js
Normal file
@ -0,0 +1,242 @@
|
||||
//// [typeGuardConstructorClassAndNumber.ts]
|
||||
// Typical case
|
||||
class C1 {
|
||||
property1: string;
|
||||
}
|
||||
|
||||
let var1: C1 | number;
|
||||
if (var1.constructor == C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (var1["constructor"] == C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (var1.constructor === C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (var1["constructor"] === C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 == var1.constructor) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 == var1["constructor"]) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 === var1.constructor) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 === var1["constructor"]) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
|
||||
if (var1.constructor != C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (var1["constructor"] != C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (var1.constructor !== C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (var1["constructor"] !== C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 != var1.constructor) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 != var1["constructor"]) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 !== var1.constructor) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 !== var1["constructor"]) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
|
||||
|
||||
//// [typeGuardConstructorClassAndNumber.js]
|
||||
// Typical case
|
||||
var C1 = /** @class */ (function () {
|
||||
function C1() {
|
||||
}
|
||||
return C1;
|
||||
}());
|
||||
var var1;
|
||||
if (var1.constructor == C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (var1["constructor"] == C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (var1.constructor === C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (var1["constructor"] === C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 == var1.constructor) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 == var1["constructor"]) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 === var1.constructor) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 === var1["constructor"]) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (var1.constructor != C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (var1["constructor"] != C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (var1.constructor !== C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (var1["constructor"] !== C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 != var1.constructor) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 != var1["constructor"]) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 !== var1.constructor) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 !== var1["constructor"]) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
@ -0,0 +1,279 @@
|
||||
=== tests/cases/compiler/typeGuardConstructorClassAndNumber.ts ===
|
||||
// Typical case
|
||||
class C1 {
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
|
||||
property1: string;
|
||||
>property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
}
|
||||
|
||||
let var1: C1 | number;
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
|
||||
if (var1.constructor == C1) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
if (var1["constructor"] == C1) {
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>"constructor" : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
if (var1.constructor === C1) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
if (var1["constructor"] === C1) {
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>"constructor" : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
if (C1 == var1.constructor) {
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
if (C1 == var1["constructor"]) {
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>"constructor" : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
if (C1 === var1.constructor) {
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
if (C1 === var1["constructor"]) {
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>"constructor" : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>property1 : Symbol(C1.property1, Decl(typeGuardConstructorClassAndNumber.ts, 1, 10))
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
|
||||
if (var1.constructor != C1) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // error
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
if (var1["constructor"] != C1) {
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>"constructor" : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // error
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
if (var1.constructor !== C1) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // error
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
if (var1["constructor"] !== C1) {
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>"constructor" : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // error
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
if (C1 != var1.constructor) {
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // error
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
if (C1 != var1["constructor"]) {
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>"constructor" : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // error
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
if (C1 !== var1.constructor) {
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // error
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
if (C1 !== var1["constructor"]) {
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorClassAndNumber.ts, 0, 0))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
>"constructor" : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
|
||||
var1.property1; // error
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorClassAndNumber.ts, 5, 3))
|
||||
}
|
||||
|
||||
@ -0,0 +1,318 @@
|
||||
=== tests/cases/compiler/typeGuardConstructorClassAndNumber.ts ===
|
||||
// Typical case
|
||||
class C1 {
|
||||
>C1 : C1
|
||||
|
||||
property1: string;
|
||||
>property1 : string
|
||||
}
|
||||
|
||||
let var1: C1 | number;
|
||||
>var1 : number | C1
|
||||
|
||||
if (var1.constructor == C1) {
|
||||
>var1.constructor == C1 : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : number | C1
|
||||
>constructor : Function
|
||||
>C1 : typeof C1
|
||||
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : string
|
||||
>var1 : C1
|
||||
>property1 : string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : number | C1
|
||||
}
|
||||
if (var1["constructor"] == C1) {
|
||||
>var1["constructor"] == C1 : boolean
|
||||
>var1["constructor"] : Function
|
||||
>var1 : number | C1
|
||||
>"constructor" : "constructor"
|
||||
>C1 : typeof C1
|
||||
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : string
|
||||
>var1 : C1
|
||||
>property1 : string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : number | C1
|
||||
}
|
||||
if (var1.constructor === C1) {
|
||||
>var1.constructor === C1 : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : number | C1
|
||||
>constructor : Function
|
||||
>C1 : typeof C1
|
||||
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : string
|
||||
>var1 : C1
|
||||
>property1 : string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : number | C1
|
||||
}
|
||||
if (var1["constructor"] === C1) {
|
||||
>var1["constructor"] === C1 : boolean
|
||||
>var1["constructor"] : Function
|
||||
>var1 : number | C1
|
||||
>"constructor" : "constructor"
|
||||
>C1 : typeof C1
|
||||
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : string
|
||||
>var1 : C1
|
||||
>property1 : string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : number | C1
|
||||
}
|
||||
if (C1 == var1.constructor) {
|
||||
>C1 == var1.constructor : boolean
|
||||
>C1 : typeof C1
|
||||
>var1.constructor : Function
|
||||
>var1 : number | C1
|
||||
>constructor : Function
|
||||
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : string
|
||||
>var1 : C1
|
||||
>property1 : string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : number | C1
|
||||
}
|
||||
if (C1 == var1["constructor"]) {
|
||||
>C1 == var1["constructor"] : boolean
|
||||
>C1 : typeof C1
|
||||
>var1["constructor"] : Function
|
||||
>var1 : number | C1
|
||||
>"constructor" : "constructor"
|
||||
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : string
|
||||
>var1 : C1
|
||||
>property1 : string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : number | C1
|
||||
}
|
||||
if (C1 === var1.constructor) {
|
||||
>C1 === var1.constructor : boolean
|
||||
>C1 : typeof C1
|
||||
>var1.constructor : Function
|
||||
>var1 : number | C1
|
||||
>constructor : Function
|
||||
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : string
|
||||
>var1 : C1
|
||||
>property1 : string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : number | C1
|
||||
}
|
||||
if (C1 === var1["constructor"]) {
|
||||
>C1 === var1["constructor"] : boolean
|
||||
>C1 : typeof C1
|
||||
>var1["constructor"] : Function
|
||||
>var1 : number | C1
|
||||
>"constructor" : "constructor"
|
||||
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
|
||||
var1.property1; // string
|
||||
>var1.property1 : string
|
||||
>var1 : C1
|
||||
>property1 : string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
>var1 : number | C1
|
||||
}
|
||||
|
||||
if (var1.constructor != C1) {
|
||||
>var1.constructor != C1 : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : number | C1
|
||||
>constructor : Function
|
||||
>C1 : typeof C1
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : number | C1
|
||||
|
||||
var1.property1; // error
|
||||
>var1.property1 : any
|
||||
>var1 : number | C1
|
||||
>property1 : any
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
}
|
||||
if (var1["constructor"] != C1) {
|
||||
>var1["constructor"] != C1 : boolean
|
||||
>var1["constructor"] : Function
|
||||
>var1 : number | C1
|
||||
>"constructor" : "constructor"
|
||||
>C1 : typeof C1
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : number | C1
|
||||
|
||||
var1.property1; // error
|
||||
>var1.property1 : any
|
||||
>var1 : number | C1
|
||||
>property1 : any
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
}
|
||||
if (var1.constructor !== C1) {
|
||||
>var1.constructor !== C1 : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : number | C1
|
||||
>constructor : Function
|
||||
>C1 : typeof C1
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : number | C1
|
||||
|
||||
var1.property1; // error
|
||||
>var1.property1 : any
|
||||
>var1 : number | C1
|
||||
>property1 : any
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
}
|
||||
if (var1["constructor"] !== C1) {
|
||||
>var1["constructor"] !== C1 : boolean
|
||||
>var1["constructor"] : Function
|
||||
>var1 : number | C1
|
||||
>"constructor" : "constructor"
|
||||
>C1 : typeof C1
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : number | C1
|
||||
|
||||
var1.property1; // error
|
||||
>var1.property1 : any
|
||||
>var1 : number | C1
|
||||
>property1 : any
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
}
|
||||
if (C1 != var1.constructor) {
|
||||
>C1 != var1.constructor : boolean
|
||||
>C1 : typeof C1
|
||||
>var1.constructor : Function
|
||||
>var1 : number | C1
|
||||
>constructor : Function
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : number | C1
|
||||
|
||||
var1.property1; // error
|
||||
>var1.property1 : any
|
||||
>var1 : number | C1
|
||||
>property1 : any
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
}
|
||||
if (C1 != var1["constructor"]) {
|
||||
>C1 != var1["constructor"] : boolean
|
||||
>C1 : typeof C1
|
||||
>var1["constructor"] : Function
|
||||
>var1 : number | C1
|
||||
>"constructor" : "constructor"
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : number | C1
|
||||
|
||||
var1.property1; // error
|
||||
>var1.property1 : any
|
||||
>var1 : number | C1
|
||||
>property1 : any
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
}
|
||||
if (C1 !== var1.constructor) {
|
||||
>C1 !== var1.constructor : boolean
|
||||
>C1 : typeof C1
|
||||
>var1.constructor : Function
|
||||
>var1 : number | C1
|
||||
>constructor : Function
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : number | C1
|
||||
|
||||
var1.property1; // error
|
||||
>var1.property1 : any
|
||||
>var1 : number | C1
|
||||
>property1 : any
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
}
|
||||
if (C1 !== var1["constructor"]) {
|
||||
>C1 !== var1["constructor"] : boolean
|
||||
>C1 : typeof C1
|
||||
>var1["constructor"] : Function
|
||||
>var1 : number | C1
|
||||
>"constructor" : "constructor"
|
||||
|
||||
var1; // C1 | number
|
||||
>var1 : number | C1
|
||||
|
||||
var1.property1; // error
|
||||
>var1.property1 : any
|
||||
>var1 : number | C1
|
||||
>property1 : any
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
>var1 : C1
|
||||
}
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
tests/cases/compiler/typeGuardConstructorDerivedClass.ts(13,10): error TS2339: Property 'property1' does not exist on type 'never'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/typeGuardConstructorDerivedClass.ts (1 errors) ====
|
||||
// Derived class with different structures
|
||||
class C1 {
|
||||
property1: number;
|
||||
}
|
||||
|
||||
class C2 extends C1 {
|
||||
property2: number;
|
||||
}
|
||||
|
||||
let var1: C2 | string;
|
||||
if (var1.constructor === C1) {
|
||||
var1; // never
|
||||
var1.property1; // error
|
||||
~~~~~~~~~
|
||||
!!! error TS2339: Property 'property1' does not exist on type 'never'.
|
||||
}
|
||||
if (var1.constructor === C2) {
|
||||
var1; // C2
|
||||
var1.property1; // number
|
||||
}
|
||||
|
||||
// Derived classes with the same structure
|
||||
class C3 {}
|
||||
|
||||
class C4 extends C3 {}
|
||||
|
||||
let var2: C4 | string;
|
||||
if (var2.constructor === C3) {
|
||||
var2; // never
|
||||
}
|
||||
if (var2.constructor === C4) {
|
||||
var2; // C4
|
||||
}
|
||||
|
||||
// Disjointly structured classes
|
||||
class C5 {
|
||||
property1: number;
|
||||
}
|
||||
|
||||
class C6 {
|
||||
property2: number;
|
||||
}
|
||||
|
||||
let let3: C6 | string;
|
||||
if (let3.constructor === C5) {
|
||||
let3; // never
|
||||
}
|
||||
if (let3.constructor === C6) {
|
||||
let3; // C6
|
||||
}
|
||||
|
||||
// Classes with the same structure
|
||||
class C7 {
|
||||
property1: number
|
||||
}
|
||||
|
||||
class C8 {
|
||||
property1: number;
|
||||
}
|
||||
|
||||
let let4: C8 | string;
|
||||
if (let4.constructor === C7) {
|
||||
let4; // never
|
||||
}
|
||||
if (let4.constructor === C8) {
|
||||
let4; // C8
|
||||
}
|
||||
|
||||
160
tests/baselines/reference/typeGuardConstructorDerivedClass.js
Normal file
160
tests/baselines/reference/typeGuardConstructorDerivedClass.js
Normal file
@ -0,0 +1,160 @@
|
||||
//// [typeGuardConstructorDerivedClass.ts]
|
||||
// Derived class with different structures
|
||||
class C1 {
|
||||
property1: number;
|
||||
}
|
||||
|
||||
class C2 extends C1 {
|
||||
property2: number;
|
||||
}
|
||||
|
||||
let var1: C2 | string;
|
||||
if (var1.constructor === C1) {
|
||||
var1; // never
|
||||
var1.property1; // error
|
||||
}
|
||||
if (var1.constructor === C2) {
|
||||
var1; // C2
|
||||
var1.property1; // number
|
||||
}
|
||||
|
||||
// Derived classes with the same structure
|
||||
class C3 {}
|
||||
|
||||
class C4 extends C3 {}
|
||||
|
||||
let var2: C4 | string;
|
||||
if (var2.constructor === C3) {
|
||||
var2; // never
|
||||
}
|
||||
if (var2.constructor === C4) {
|
||||
var2; // C4
|
||||
}
|
||||
|
||||
// Disjointly structured classes
|
||||
class C5 {
|
||||
property1: number;
|
||||
}
|
||||
|
||||
class C6 {
|
||||
property2: number;
|
||||
}
|
||||
|
||||
let let3: C6 | string;
|
||||
if (let3.constructor === C5) {
|
||||
let3; // never
|
||||
}
|
||||
if (let3.constructor === C6) {
|
||||
let3; // C6
|
||||
}
|
||||
|
||||
// Classes with the same structure
|
||||
class C7 {
|
||||
property1: number
|
||||
}
|
||||
|
||||
class C8 {
|
||||
property1: number;
|
||||
}
|
||||
|
||||
let let4: C8 | string;
|
||||
if (let4.constructor === C7) {
|
||||
let4; // never
|
||||
}
|
||||
if (let4.constructor === C8) {
|
||||
let4; // C8
|
||||
}
|
||||
|
||||
|
||||
//// [typeGuardConstructorDerivedClass.js]
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
// Derived class with different structures
|
||||
var C1 = /** @class */ (function () {
|
||||
function C1() {
|
||||
}
|
||||
return C1;
|
||||
}());
|
||||
var C2 = /** @class */ (function (_super) {
|
||||
__extends(C2, _super);
|
||||
function C2() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return C2;
|
||||
}(C1));
|
||||
var var1;
|
||||
if (var1.constructor === C1) {
|
||||
var1; // never
|
||||
var1.property1; // error
|
||||
}
|
||||
if (var1.constructor === C2) {
|
||||
var1; // C2
|
||||
var1.property1; // number
|
||||
}
|
||||
// Derived classes with the same structure
|
||||
var C3 = /** @class */ (function () {
|
||||
function C3() {
|
||||
}
|
||||
return C3;
|
||||
}());
|
||||
var C4 = /** @class */ (function (_super) {
|
||||
__extends(C4, _super);
|
||||
function C4() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return C4;
|
||||
}(C3));
|
||||
var var2;
|
||||
if (var2.constructor === C3) {
|
||||
var2; // never
|
||||
}
|
||||
if (var2.constructor === C4) {
|
||||
var2; // C4
|
||||
}
|
||||
// Disjointly structured classes
|
||||
var C5 = /** @class */ (function () {
|
||||
function C5() {
|
||||
}
|
||||
return C5;
|
||||
}());
|
||||
var C6 = /** @class */ (function () {
|
||||
function C6() {
|
||||
}
|
||||
return C6;
|
||||
}());
|
||||
var let3;
|
||||
if (let3.constructor === C5) {
|
||||
let3; // never
|
||||
}
|
||||
if (let3.constructor === C6) {
|
||||
let3; // C6
|
||||
}
|
||||
// Classes with the same structure
|
||||
var C7 = /** @class */ (function () {
|
||||
function C7() {
|
||||
}
|
||||
return C7;
|
||||
}());
|
||||
var C8 = /** @class */ (function () {
|
||||
function C8() {
|
||||
}
|
||||
return C8;
|
||||
}());
|
||||
var let4;
|
||||
if (let4.constructor === C7) {
|
||||
let4; // never
|
||||
}
|
||||
if (let4.constructor === C8) {
|
||||
let4; // C8
|
||||
}
|
||||
@ -0,0 +1,155 @@
|
||||
=== tests/cases/compiler/typeGuardConstructorDerivedClass.ts ===
|
||||
// Derived class with different structures
|
||||
class C1 {
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorDerivedClass.ts, 0, 0))
|
||||
|
||||
property1: number;
|
||||
>property1 : Symbol(C1.property1, Decl(typeGuardConstructorDerivedClass.ts, 1, 10))
|
||||
}
|
||||
|
||||
class C2 extends C1 {
|
||||
>C2 : Symbol(C2, Decl(typeGuardConstructorDerivedClass.ts, 3, 1))
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorDerivedClass.ts, 0, 0))
|
||||
|
||||
property2: number;
|
||||
>property2 : Symbol(C2.property2, Decl(typeGuardConstructorDerivedClass.ts, 5, 21))
|
||||
}
|
||||
|
||||
let var1: C2 | string;
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorDerivedClass.ts, 9, 3))
|
||||
>C2 : Symbol(C2, Decl(typeGuardConstructorDerivedClass.ts, 3, 1))
|
||||
|
||||
if (var1.constructor === C1) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorDerivedClass.ts, 9, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C1 : Symbol(C1, Decl(typeGuardConstructorDerivedClass.ts, 0, 0))
|
||||
|
||||
var1; // never
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorDerivedClass.ts, 9, 3))
|
||||
|
||||
var1.property1; // error
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorDerivedClass.ts, 9, 3))
|
||||
}
|
||||
if (var1.constructor === C2) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorDerivedClass.ts, 9, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C2 : Symbol(C2, Decl(typeGuardConstructorDerivedClass.ts, 3, 1))
|
||||
|
||||
var1; // C2
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorDerivedClass.ts, 9, 3))
|
||||
|
||||
var1.property1; // number
|
||||
>var1.property1 : Symbol(C1.property1, Decl(typeGuardConstructorDerivedClass.ts, 1, 10))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorDerivedClass.ts, 9, 3))
|
||||
>property1 : Symbol(C1.property1, Decl(typeGuardConstructorDerivedClass.ts, 1, 10))
|
||||
}
|
||||
|
||||
// Derived classes with the same structure
|
||||
class C3 {}
|
||||
>C3 : Symbol(C3, Decl(typeGuardConstructorDerivedClass.ts, 17, 1))
|
||||
|
||||
class C4 extends C3 {}
|
||||
>C4 : Symbol(C4, Decl(typeGuardConstructorDerivedClass.ts, 20, 11))
|
||||
>C3 : Symbol(C3, Decl(typeGuardConstructorDerivedClass.ts, 17, 1))
|
||||
|
||||
let var2: C4 | string;
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorDerivedClass.ts, 24, 3))
|
||||
>C4 : Symbol(C4, Decl(typeGuardConstructorDerivedClass.ts, 20, 11))
|
||||
|
||||
if (var2.constructor === C3) {
|
||||
>var2.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorDerivedClass.ts, 24, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C3 : Symbol(C3, Decl(typeGuardConstructorDerivedClass.ts, 17, 1))
|
||||
|
||||
var2; // never
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorDerivedClass.ts, 24, 3))
|
||||
}
|
||||
if (var2.constructor === C4) {
|
||||
>var2.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorDerivedClass.ts, 24, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C4 : Symbol(C4, Decl(typeGuardConstructorDerivedClass.ts, 20, 11))
|
||||
|
||||
var2; // C4
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorDerivedClass.ts, 24, 3))
|
||||
}
|
||||
|
||||
// Disjointly structured classes
|
||||
class C5 {
|
||||
>C5 : Symbol(C5, Decl(typeGuardConstructorDerivedClass.ts, 30, 1))
|
||||
|
||||
property1: number;
|
||||
>property1 : Symbol(C5.property1, Decl(typeGuardConstructorDerivedClass.ts, 33, 10))
|
||||
}
|
||||
|
||||
class C6 {
|
||||
>C6 : Symbol(C6, Decl(typeGuardConstructorDerivedClass.ts, 35, 1))
|
||||
|
||||
property2: number;
|
||||
>property2 : Symbol(C6.property2, Decl(typeGuardConstructorDerivedClass.ts, 37, 10))
|
||||
}
|
||||
|
||||
let let3: C6 | string;
|
||||
>let3 : Symbol(let3, Decl(typeGuardConstructorDerivedClass.ts, 41, 3))
|
||||
>C6 : Symbol(C6, Decl(typeGuardConstructorDerivedClass.ts, 35, 1))
|
||||
|
||||
if (let3.constructor === C5) {
|
||||
>let3.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>let3 : Symbol(let3, Decl(typeGuardConstructorDerivedClass.ts, 41, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C5 : Symbol(C5, Decl(typeGuardConstructorDerivedClass.ts, 30, 1))
|
||||
|
||||
let3; // never
|
||||
>let3 : Symbol(let3, Decl(typeGuardConstructorDerivedClass.ts, 41, 3))
|
||||
}
|
||||
if (let3.constructor === C6) {
|
||||
>let3.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>let3 : Symbol(let3, Decl(typeGuardConstructorDerivedClass.ts, 41, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C6 : Symbol(C6, Decl(typeGuardConstructorDerivedClass.ts, 35, 1))
|
||||
|
||||
let3; // C6
|
||||
>let3 : Symbol(let3, Decl(typeGuardConstructorDerivedClass.ts, 41, 3))
|
||||
}
|
||||
|
||||
// Classes with the same structure
|
||||
class C7 {
|
||||
>C7 : Symbol(C7, Decl(typeGuardConstructorDerivedClass.ts, 47, 1))
|
||||
|
||||
property1: number
|
||||
>property1 : Symbol(C7.property1, Decl(typeGuardConstructorDerivedClass.ts, 50, 10))
|
||||
}
|
||||
|
||||
class C8 {
|
||||
>C8 : Symbol(C8, Decl(typeGuardConstructorDerivedClass.ts, 52, 1))
|
||||
|
||||
property1: number;
|
||||
>property1 : Symbol(C8.property1, Decl(typeGuardConstructorDerivedClass.ts, 54, 10))
|
||||
}
|
||||
|
||||
let let4: C8 | string;
|
||||
>let4 : Symbol(let4, Decl(typeGuardConstructorDerivedClass.ts, 58, 3))
|
||||
>C8 : Symbol(C8, Decl(typeGuardConstructorDerivedClass.ts, 52, 1))
|
||||
|
||||
if (let4.constructor === C7) {
|
||||
>let4.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>let4 : Symbol(let4, Decl(typeGuardConstructorDerivedClass.ts, 58, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C7 : Symbol(C7, Decl(typeGuardConstructorDerivedClass.ts, 47, 1))
|
||||
|
||||
let4; // never
|
||||
>let4 : Symbol(let4, Decl(typeGuardConstructorDerivedClass.ts, 58, 3))
|
||||
}
|
||||
if (let4.constructor === C8) {
|
||||
>let4.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>let4 : Symbol(let4, Decl(typeGuardConstructorDerivedClass.ts, 58, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>C8 : Symbol(C8, Decl(typeGuardConstructorDerivedClass.ts, 52, 1))
|
||||
|
||||
let4; // C8
|
||||
>let4 : Symbol(let4, Decl(typeGuardConstructorDerivedClass.ts, 58, 3))
|
||||
}
|
||||
|
||||
161
tests/baselines/reference/typeGuardConstructorDerivedClass.types
Normal file
161
tests/baselines/reference/typeGuardConstructorDerivedClass.types
Normal file
@ -0,0 +1,161 @@
|
||||
=== tests/cases/compiler/typeGuardConstructorDerivedClass.ts ===
|
||||
// Derived class with different structures
|
||||
class C1 {
|
||||
>C1 : C1
|
||||
|
||||
property1: number;
|
||||
>property1 : number
|
||||
}
|
||||
|
||||
class C2 extends C1 {
|
||||
>C2 : C2
|
||||
>C1 : C1
|
||||
|
||||
property2: number;
|
||||
>property2 : number
|
||||
}
|
||||
|
||||
let var1: C2 | string;
|
||||
>var1 : string | C2
|
||||
|
||||
if (var1.constructor === C1) {
|
||||
>var1.constructor === C1 : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : string | C2
|
||||
>constructor : Function
|
||||
>C1 : typeof C1
|
||||
|
||||
var1; // never
|
||||
>var1 : never
|
||||
|
||||
var1.property1; // error
|
||||
>var1.property1 : any
|
||||
>var1 : never
|
||||
>property1 : any
|
||||
}
|
||||
if (var1.constructor === C2) {
|
||||
>var1.constructor === C2 : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : string | C2
|
||||
>constructor : Function
|
||||
>C2 : typeof C2
|
||||
|
||||
var1; // C2
|
||||
>var1 : C2
|
||||
|
||||
var1.property1; // number
|
||||
>var1.property1 : number
|
||||
>var1 : C2
|
||||
>property1 : number
|
||||
}
|
||||
|
||||
// Derived classes with the same structure
|
||||
class C3 {}
|
||||
>C3 : C3
|
||||
|
||||
class C4 extends C3 {}
|
||||
>C4 : C4
|
||||
>C3 : C3
|
||||
|
||||
let var2: C4 | string;
|
||||
>var2 : string | C4
|
||||
|
||||
if (var2.constructor === C3) {
|
||||
>var2.constructor === C3 : boolean
|
||||
>var2.constructor : Function
|
||||
>var2 : string | C4
|
||||
>constructor : Function
|
||||
>C3 : typeof C3
|
||||
|
||||
var2; // never
|
||||
>var2 : never
|
||||
}
|
||||
if (var2.constructor === C4) {
|
||||
>var2.constructor === C4 : boolean
|
||||
>var2.constructor : Function
|
||||
>var2 : string | C4
|
||||
>constructor : Function
|
||||
>C4 : typeof C4
|
||||
|
||||
var2; // C4
|
||||
>var2 : C4
|
||||
}
|
||||
|
||||
// Disjointly structured classes
|
||||
class C5 {
|
||||
>C5 : C5
|
||||
|
||||
property1: number;
|
||||
>property1 : number
|
||||
}
|
||||
|
||||
class C6 {
|
||||
>C6 : C6
|
||||
|
||||
property2: number;
|
||||
>property2 : number
|
||||
}
|
||||
|
||||
let let3: C6 | string;
|
||||
>let3 : string | C6
|
||||
|
||||
if (let3.constructor === C5) {
|
||||
>let3.constructor === C5 : boolean
|
||||
>let3.constructor : Function
|
||||
>let3 : string | C6
|
||||
>constructor : Function
|
||||
>C5 : typeof C5
|
||||
|
||||
let3; // never
|
||||
>let3 : never
|
||||
}
|
||||
if (let3.constructor === C6) {
|
||||
>let3.constructor === C6 : boolean
|
||||
>let3.constructor : Function
|
||||
>let3 : string | C6
|
||||
>constructor : Function
|
||||
>C6 : typeof C6
|
||||
|
||||
let3; // C6
|
||||
>let3 : C6
|
||||
}
|
||||
|
||||
// Classes with the same structure
|
||||
class C7 {
|
||||
>C7 : C7
|
||||
|
||||
property1: number
|
||||
>property1 : number
|
||||
}
|
||||
|
||||
class C8 {
|
||||
>C8 : C8
|
||||
|
||||
property1: number;
|
||||
>property1 : number
|
||||
}
|
||||
|
||||
let let4: C8 | string;
|
||||
>let4 : string | C8
|
||||
|
||||
if (let4.constructor === C7) {
|
||||
>let4.constructor === C7 : boolean
|
||||
>let4.constructor : Function
|
||||
>let4 : string | C8
|
||||
>constructor : Function
|
||||
>C7 : typeof C7
|
||||
|
||||
let4; // never
|
||||
>let4 : never
|
||||
}
|
||||
if (let4.constructor === C8) {
|
||||
>let4.constructor === C8 : boolean
|
||||
>let4.constructor : Function
|
||||
>let4 : string | C8
|
||||
>constructor : Function
|
||||
>C8 : typeof C8
|
||||
|
||||
let4; // C8
|
||||
>let4 : C8
|
||||
}
|
||||
|
||||
45
tests/baselines/reference/typeGuardConstructorNarrowAny.js
Normal file
45
tests/baselines/reference/typeGuardConstructorNarrowAny.js
Normal file
@ -0,0 +1,45 @@
|
||||
//// [typeGuardConstructorNarrowAny.ts]
|
||||
// Narrowing any to primitives
|
||||
let var1: any;
|
||||
|
||||
if (var1.constructor === String) {
|
||||
var1; // String
|
||||
}
|
||||
if (var1.constructor === Number) {
|
||||
var1; // Number
|
||||
}
|
||||
if (var1.constructor === Boolean) {
|
||||
var1; // Boolean
|
||||
}
|
||||
if (var1.constructor === Array) {
|
||||
var1; // any[]
|
||||
}
|
||||
if (var1.constructor === Symbol) {
|
||||
var1; // Symbol
|
||||
}
|
||||
if (var1.constructor === BigInt) {
|
||||
var1; // BigInt
|
||||
}
|
||||
|
||||
|
||||
//// [typeGuardConstructorNarrowAny.js]
|
||||
// Narrowing any to primitives
|
||||
let var1;
|
||||
if (var1.constructor === String) {
|
||||
var1; // String
|
||||
}
|
||||
if (var1.constructor === Number) {
|
||||
var1; // Number
|
||||
}
|
||||
if (var1.constructor === Boolean) {
|
||||
var1; // Boolean
|
||||
}
|
||||
if (var1.constructor === Array) {
|
||||
var1; // any[]
|
||||
}
|
||||
if (var1.constructor === Symbol) {
|
||||
var1; // Symbol
|
||||
}
|
||||
if (var1.constructor === BigInt) {
|
||||
var1; // BigInt
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
=== tests/cases/compiler/typeGuardConstructorNarrowAny.ts ===
|
||||
// Narrowing any to primitives
|
||||
let var1: any;
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowAny.ts, 1, 3))
|
||||
|
||||
if (var1.constructor === String) {
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowAny.ts, 1, 3))
|
||||
>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --) ... and 5 more)
|
||||
|
||||
var1; // String
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowAny.ts, 1, 3))
|
||||
}
|
||||
if (var1.constructor === Number) {
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowAny.ts, 1, 3))
|
||||
>Number : Symbol(Number, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // Number
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowAny.ts, 1, 3))
|
||||
}
|
||||
if (var1.constructor === Boolean) {
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowAny.ts, 1, 3))
|
||||
>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // Boolean
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowAny.ts, 1, 3))
|
||||
}
|
||||
if (var1.constructor === Array) {
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowAny.ts, 1, 3))
|
||||
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 2 more)
|
||||
|
||||
var1; // any[]
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowAny.ts, 1, 3))
|
||||
}
|
||||
if (var1.constructor === Symbol) {
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowAny.ts, 1, 3))
|
||||
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
|
||||
|
||||
var1; // Symbol
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowAny.ts, 1, 3))
|
||||
}
|
||||
if (var1.constructor === BigInt) {
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowAny.ts, 1, 3))
|
||||
>BigInt : Symbol(BigInt, Decl(lib.es2020.bigint.d.ts, --, --), Decl(lib.es2020.bigint.d.ts, --, --))
|
||||
|
||||
var1; // BigInt
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowAny.ts, 1, 3))
|
||||
}
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
=== tests/cases/compiler/typeGuardConstructorNarrowAny.ts ===
|
||||
// Narrowing any to primitives
|
||||
let var1: any;
|
||||
>var1 : any
|
||||
|
||||
if (var1.constructor === String) {
|
||||
>var1.constructor === String : boolean
|
||||
>var1.constructor : any
|
||||
>var1 : any
|
||||
>constructor : any
|
||||
>String : StringConstructor
|
||||
|
||||
var1; // String
|
||||
>var1 : String
|
||||
}
|
||||
if (var1.constructor === Number) {
|
||||
>var1.constructor === Number : boolean
|
||||
>var1.constructor : any
|
||||
>var1 : any
|
||||
>constructor : any
|
||||
>Number : NumberConstructor
|
||||
|
||||
var1; // Number
|
||||
>var1 : Number
|
||||
}
|
||||
if (var1.constructor === Boolean) {
|
||||
>var1.constructor === Boolean : boolean
|
||||
>var1.constructor : any
|
||||
>var1 : any
|
||||
>constructor : any
|
||||
>Boolean : BooleanConstructor
|
||||
|
||||
var1; // Boolean
|
||||
>var1 : Boolean
|
||||
}
|
||||
if (var1.constructor === Array) {
|
||||
>var1.constructor === Array : boolean
|
||||
>var1.constructor : any
|
||||
>var1 : any
|
||||
>constructor : any
|
||||
>Array : ArrayConstructor
|
||||
|
||||
var1; // any[]
|
||||
>var1 : any[]
|
||||
}
|
||||
if (var1.constructor === Symbol) {
|
||||
>var1.constructor === Symbol : boolean
|
||||
>var1.constructor : any
|
||||
>var1 : any
|
||||
>constructor : any
|
||||
>Symbol : SymbolConstructor
|
||||
|
||||
var1; // Symbol
|
||||
>var1 : Symbol
|
||||
}
|
||||
if (var1.constructor === BigInt) {
|
||||
>var1.constructor === BigInt : boolean
|
||||
>var1.constructor : any
|
||||
>var1 : any
|
||||
>constructor : any
|
||||
>BigInt : BigIntConstructor
|
||||
|
||||
var1; // BigInt
|
||||
>var1 : BigInt
|
||||
}
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
//// [typeGuardConstructorNarrowPrimitivesInUnion.ts]
|
||||
// Union of primitives, number, arrays, and C1
|
||||
let var1: number | "hello" | "world" | true | false | number[] | string[];
|
||||
|
||||
if (var1.constructor === Number) {
|
||||
var1; // number
|
||||
}
|
||||
|
||||
if (var1.constructor === String) {
|
||||
var1; // "hello" | "world"
|
||||
}
|
||||
|
||||
if (var1.constructor === Boolean) {
|
||||
var1; // boolean
|
||||
}
|
||||
|
||||
if (var1.constructor === Array) {
|
||||
var1; // number[] | string[]
|
||||
}
|
||||
|
||||
|
||||
//// [typeGuardConstructorNarrowPrimitivesInUnion.js]
|
||||
// Union of primitives, number, arrays, and C1
|
||||
var var1;
|
||||
if (var1.constructor === Number) {
|
||||
var1; // number
|
||||
}
|
||||
if (var1.constructor === String) {
|
||||
var1; // "hello" | "world"
|
||||
}
|
||||
if (var1.constructor === Boolean) {
|
||||
var1; // boolean
|
||||
}
|
||||
if (var1.constructor === Array) {
|
||||
var1; // number[] | string[]
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
=== tests/cases/compiler/typeGuardConstructorNarrowPrimitivesInUnion.ts ===
|
||||
// Union of primitives, number, arrays, and C1
|
||||
let var1: number | "hello" | "world" | true | false | number[] | string[];
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowPrimitivesInUnion.ts, 1, 3))
|
||||
|
||||
if (var1.constructor === Number) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowPrimitivesInUnion.ts, 1, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>Number : Symbol(Number, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // number
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowPrimitivesInUnion.ts, 1, 3))
|
||||
}
|
||||
|
||||
if (var1.constructor === String) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowPrimitivesInUnion.ts, 1, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // "hello" | "world"
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowPrimitivesInUnion.ts, 1, 3))
|
||||
}
|
||||
|
||||
if (var1.constructor === Boolean) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowPrimitivesInUnion.ts, 1, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // boolean
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowPrimitivesInUnion.ts, 1, 3))
|
||||
}
|
||||
|
||||
if (var1.constructor === Array) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowPrimitivesInUnion.ts, 1, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // number[] | string[]
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorNarrowPrimitivesInUnion.ts, 1, 3))
|
||||
}
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
=== tests/cases/compiler/typeGuardConstructorNarrowPrimitivesInUnion.ts ===
|
||||
// Union of primitives, number, arrays, and C1
|
||||
let var1: number | "hello" | "world" | true | false | number[] | string[];
|
||||
>var1 : number | boolean | "hello" | "world" | number[] | string[]
|
||||
>true : true
|
||||
>false : false
|
||||
|
||||
if (var1.constructor === Number) {
|
||||
>var1.constructor === Number : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : number | boolean | "hello" | "world" | number[] | string[]
|
||||
>constructor : Function
|
||||
>Number : NumberConstructor
|
||||
|
||||
var1; // number
|
||||
>var1 : number
|
||||
}
|
||||
|
||||
if (var1.constructor === String) {
|
||||
>var1.constructor === String : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : number | boolean | "hello" | "world" | number[] | string[]
|
||||
>constructor : Function
|
||||
>String : StringConstructor
|
||||
|
||||
var1; // "hello" | "world"
|
||||
>var1 : "hello" | "world"
|
||||
}
|
||||
|
||||
if (var1.constructor === Boolean) {
|
||||
>var1.constructor === Boolean : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : number | boolean | "hello" | "world" | number[] | string[]
|
||||
>constructor : Function
|
||||
>Boolean : BooleanConstructor
|
||||
|
||||
var1; // boolean
|
||||
>var1 : boolean
|
||||
}
|
||||
|
||||
if (var1.constructor === Array) {
|
||||
>var1.constructor === Array : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : number | boolean | "hello" | "world" | number[] | string[]
|
||||
>constructor : Function
|
||||
>Array : ArrayConstructor
|
||||
|
||||
var1; // number[] | string[]
|
||||
>var1 : number[] | string[]
|
||||
}
|
||||
|
||||
@ -0,0 +1,79 @@
|
||||
//// [typeGuardConstructorPrimitiveTypes.ts]
|
||||
// Narrow a union of primitive types
|
||||
let var1: string | number | boolean | any[] | symbol | bigint;
|
||||
if (var1.constructor === String) {
|
||||
var1; // string
|
||||
}
|
||||
if (var1.constructor === Number) {
|
||||
var1; // number
|
||||
}
|
||||
if (var1.constructor === Boolean) {
|
||||
var1; // boolean
|
||||
}
|
||||
if (var1.constructor === Array) {
|
||||
var1; // any[]
|
||||
}
|
||||
if (var1.constructor === Symbol) {
|
||||
var1; // symbol
|
||||
}
|
||||
if (var1.constructor === BigInt) {
|
||||
var1; // bigint
|
||||
}
|
||||
|
||||
// Narrow a union of primitive object types
|
||||
let var2: String | Number | Boolean | Symbol | BigInt;
|
||||
if (var2.constructor === String) {
|
||||
var2; // String
|
||||
}
|
||||
if (var2.constructor === Number) {
|
||||
var2; // Number
|
||||
}
|
||||
if (var2.constructor === Boolean) {
|
||||
var2; // Boolean
|
||||
}
|
||||
if (var2.constructor === Symbol) {
|
||||
var2; // Symbol
|
||||
}
|
||||
if (var2.constructor === BigInt) {
|
||||
var2; // BigInt
|
||||
}
|
||||
|
||||
|
||||
//// [typeGuardConstructorPrimitiveTypes.js]
|
||||
// Narrow a union of primitive types
|
||||
let var1;
|
||||
if (var1.constructor === String) {
|
||||
var1; // string
|
||||
}
|
||||
if (var1.constructor === Number) {
|
||||
var1; // number
|
||||
}
|
||||
if (var1.constructor === Boolean) {
|
||||
var1; // boolean
|
||||
}
|
||||
if (var1.constructor === Array) {
|
||||
var1; // any[]
|
||||
}
|
||||
if (var1.constructor === Symbol) {
|
||||
var1; // symbol
|
||||
}
|
||||
if (var1.constructor === BigInt) {
|
||||
var1; // bigint
|
||||
}
|
||||
// Narrow a union of primitive object types
|
||||
let var2;
|
||||
if (var2.constructor === String) {
|
||||
var2; // String
|
||||
}
|
||||
if (var2.constructor === Number) {
|
||||
var2; // Number
|
||||
}
|
||||
if (var2.constructor === Boolean) {
|
||||
var2; // Boolean
|
||||
}
|
||||
if (var2.constructor === Symbol) {
|
||||
var2; // Symbol
|
||||
}
|
||||
if (var2.constructor === BigInt) {
|
||||
var2; // BigInt
|
||||
}
|
||||
@ -0,0 +1,115 @@
|
||||
=== tests/cases/compiler/typeGuardConstructorPrimitiveTypes.ts ===
|
||||
// Narrow a union of primitive types
|
||||
let var1: string | number | boolean | any[] | symbol | bigint;
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorPrimitiveTypes.ts, 1, 3))
|
||||
|
||||
if (var1.constructor === String) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorPrimitiveTypes.ts, 1, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --) ... and 5 more)
|
||||
|
||||
var1; // string
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorPrimitiveTypes.ts, 1, 3))
|
||||
}
|
||||
if (var1.constructor === Number) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorPrimitiveTypes.ts, 1, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>Number : Symbol(Number, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // number
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorPrimitiveTypes.ts, 1, 3))
|
||||
}
|
||||
if (var1.constructor === Boolean) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorPrimitiveTypes.ts, 1, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var1; // boolean
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorPrimitiveTypes.ts, 1, 3))
|
||||
}
|
||||
if (var1.constructor === Array) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorPrimitiveTypes.ts, 1, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 2 more)
|
||||
|
||||
var1; // any[]
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorPrimitiveTypes.ts, 1, 3))
|
||||
}
|
||||
if (var1.constructor === Symbol) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorPrimitiveTypes.ts, 1, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
|
||||
|
||||
var1; // symbol
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorPrimitiveTypes.ts, 1, 3))
|
||||
}
|
||||
if (var1.constructor === BigInt) {
|
||||
>var1.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorPrimitiveTypes.ts, 1, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>BigInt : Symbol(BigInt, Decl(lib.es2020.bigint.d.ts, --, --), Decl(lib.es2020.bigint.d.ts, --, --))
|
||||
|
||||
var1; // bigint
|
||||
>var1 : Symbol(var1, Decl(typeGuardConstructorPrimitiveTypes.ts, 1, 3))
|
||||
}
|
||||
|
||||
// Narrow a union of primitive object types
|
||||
let var2: String | Number | Boolean | Symbol | BigInt;
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorPrimitiveTypes.ts, 22, 3))
|
||||
>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --) ... and 5 more)
|
||||
>Number : Symbol(Number, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
|
||||
>BigInt : Symbol(BigInt, Decl(lib.es2020.bigint.d.ts, --, --), Decl(lib.es2020.bigint.d.ts, --, --))
|
||||
|
||||
if (var2.constructor === String) {
|
||||
>var2.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorPrimitiveTypes.ts, 22, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --) ... and 5 more)
|
||||
|
||||
var2; // String
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorPrimitiveTypes.ts, 22, 3))
|
||||
}
|
||||
if (var2.constructor === Number) {
|
||||
>var2.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorPrimitiveTypes.ts, 22, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>Number : Symbol(Number, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var2; // Number
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorPrimitiveTypes.ts, 22, 3))
|
||||
}
|
||||
if (var2.constructor === Boolean) {
|
||||
>var2.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorPrimitiveTypes.ts, 22, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var2; // Boolean
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorPrimitiveTypes.ts, 22, 3))
|
||||
}
|
||||
if (var2.constructor === Symbol) {
|
||||
>var2.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorPrimitiveTypes.ts, 22, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
|
||||
|
||||
var2; // Symbol
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorPrimitiveTypes.ts, 22, 3))
|
||||
}
|
||||
if (var2.constructor === BigInt) {
|
||||
>var2.constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorPrimitiveTypes.ts, 22, 3))
|
||||
>constructor : Symbol(Object.constructor, Decl(lib.es5.d.ts, --, --))
|
||||
>BigInt : Symbol(BigInt, Decl(lib.es2020.bigint.d.ts, --, --), Decl(lib.es2020.bigint.d.ts, --, --))
|
||||
|
||||
var2; // BigInt
|
||||
>var2 : Symbol(var2, Decl(typeGuardConstructorPrimitiveTypes.ts, 22, 3))
|
||||
}
|
||||
|
||||
@ -0,0 +1,121 @@
|
||||
=== tests/cases/compiler/typeGuardConstructorPrimitiveTypes.ts ===
|
||||
// Narrow a union of primitive types
|
||||
let var1: string | number | boolean | any[] | symbol | bigint;
|
||||
>var1 : string | number | bigint | boolean | symbol | any[]
|
||||
|
||||
if (var1.constructor === String) {
|
||||
>var1.constructor === String : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : string | number | bigint | boolean | symbol | any[]
|
||||
>constructor : Function
|
||||
>String : StringConstructor
|
||||
|
||||
var1; // string
|
||||
>var1 : string
|
||||
}
|
||||
if (var1.constructor === Number) {
|
||||
>var1.constructor === Number : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : string | number | bigint | boolean | symbol | any[]
|
||||
>constructor : Function
|
||||
>Number : NumberConstructor
|
||||
|
||||
var1; // number
|
||||
>var1 : number
|
||||
}
|
||||
if (var1.constructor === Boolean) {
|
||||
>var1.constructor === Boolean : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : string | number | bigint | boolean | symbol | any[]
|
||||
>constructor : Function
|
||||
>Boolean : BooleanConstructor
|
||||
|
||||
var1; // boolean
|
||||
>var1 : boolean
|
||||
}
|
||||
if (var1.constructor === Array) {
|
||||
>var1.constructor === Array : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : string | number | bigint | boolean | symbol | any[]
|
||||
>constructor : Function
|
||||
>Array : ArrayConstructor
|
||||
|
||||
var1; // any[]
|
||||
>var1 : any[]
|
||||
}
|
||||
if (var1.constructor === Symbol) {
|
||||
>var1.constructor === Symbol : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : string | number | bigint | boolean | symbol | any[]
|
||||
>constructor : Function
|
||||
>Symbol : SymbolConstructor
|
||||
|
||||
var1; // symbol
|
||||
>var1 : symbol
|
||||
}
|
||||
if (var1.constructor === BigInt) {
|
||||
>var1.constructor === BigInt : boolean
|
||||
>var1.constructor : Function
|
||||
>var1 : string | number | bigint | boolean | symbol | any[]
|
||||
>constructor : Function
|
||||
>BigInt : BigIntConstructor
|
||||
|
||||
var1; // bigint
|
||||
>var1 : bigint
|
||||
}
|
||||
|
||||
// Narrow a union of primitive object types
|
||||
let var2: String | Number | Boolean | Symbol | BigInt;
|
||||
>var2 : String | Number | Boolean | BigInt | Symbol
|
||||
|
||||
if (var2.constructor === String) {
|
||||
>var2.constructor === String : boolean
|
||||
>var2.constructor : Function
|
||||
>var2 : String | Number | Boolean | BigInt | Symbol
|
||||
>constructor : Function
|
||||
>String : StringConstructor
|
||||
|
||||
var2; // String
|
||||
>var2 : String
|
||||
}
|
||||
if (var2.constructor === Number) {
|
||||
>var2.constructor === Number : boolean
|
||||
>var2.constructor : Function
|
||||
>var2 : String | Number | Boolean | BigInt | Symbol
|
||||
>constructor : Function
|
||||
>Number : NumberConstructor
|
||||
|
||||
var2; // Number
|
||||
>var2 : Number
|
||||
}
|
||||
if (var2.constructor === Boolean) {
|
||||
>var2.constructor === Boolean : boolean
|
||||
>var2.constructor : Function
|
||||
>var2 : String | Number | Boolean | BigInt | Symbol
|
||||
>constructor : Function
|
||||
>Boolean : BooleanConstructor
|
||||
|
||||
var2; // Boolean
|
||||
>var2 : Boolean
|
||||
}
|
||||
if (var2.constructor === Symbol) {
|
||||
>var2.constructor === Symbol : boolean
|
||||
>var2.constructor : Function
|
||||
>var2 : String | Number | Boolean | BigInt | Symbol
|
||||
>constructor : Function
|
||||
>Symbol : SymbolConstructor
|
||||
|
||||
var2; // Symbol
|
||||
>var2 : Symbol
|
||||
}
|
||||
if (var2.constructor === BigInt) {
|
||||
>var2.constructor === BigInt : boolean
|
||||
>var2.constructor : Function
|
||||
>var2 : String | Number | Boolean | BigInt | Symbol
|
||||
>constructor : Function
|
||||
>BigInt : BigIntConstructor
|
||||
|
||||
var2; // BigInt
|
||||
>var2 : BigInt
|
||||
}
|
||||
|
||||
119
tests/cases/compiler/typeGuardConstructorClassAndNumber.ts
Normal file
119
tests/cases/compiler/typeGuardConstructorClassAndNumber.ts
Normal file
@ -0,0 +1,119 @@
|
||||
// Typical case
|
||||
class C1 {
|
||||
property1: string;
|
||||
}
|
||||
|
||||
let var1: C1 | number;
|
||||
if (var1.constructor == C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (var1["constructor"] == C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (var1.constructor === C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (var1["constructor"] === C1) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 == var1.constructor) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 == var1["constructor"]) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 === var1.constructor) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
if (C1 === var1["constructor"]) {
|
||||
var1; // C1
|
||||
var1.property1; // string
|
||||
}
|
||||
else {
|
||||
var1; // number | C1
|
||||
}
|
||||
|
||||
if (var1.constructor != C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (var1["constructor"] != C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (var1.constructor !== C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (var1["constructor"] !== C1) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 != var1.constructor) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 != var1["constructor"]) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 !== var1.constructor) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
if (C1 !== var1["constructor"]) {
|
||||
var1; // C1 | number
|
||||
var1.property1; // error
|
||||
}
|
||||
else {
|
||||
var1; // C1
|
||||
}
|
||||
65
tests/cases/compiler/typeGuardConstructorDerivedClass.ts
Normal file
65
tests/cases/compiler/typeGuardConstructorDerivedClass.ts
Normal file
@ -0,0 +1,65 @@
|
||||
// Derived class with different structures
|
||||
class C1 {
|
||||
property1: number;
|
||||
}
|
||||
|
||||
class C2 extends C1 {
|
||||
property2: number;
|
||||
}
|
||||
|
||||
let var1: C2 | string;
|
||||
if (var1.constructor === C1) {
|
||||
var1; // never
|
||||
var1.property1; // error
|
||||
}
|
||||
if (var1.constructor === C2) {
|
||||
var1; // C2
|
||||
var1.property1; // number
|
||||
}
|
||||
|
||||
// Derived classes with the same structure
|
||||
class C3 {}
|
||||
|
||||
class C4 extends C3 {}
|
||||
|
||||
let var2: C4 | string;
|
||||
if (var2.constructor === C3) {
|
||||
var2; // never
|
||||
}
|
||||
if (var2.constructor === C4) {
|
||||
var2; // C4
|
||||
}
|
||||
|
||||
// Disjointly structured classes
|
||||
class C5 {
|
||||
property1: number;
|
||||
}
|
||||
|
||||
class C6 {
|
||||
property2: number;
|
||||
}
|
||||
|
||||
let let3: C6 | string;
|
||||
if (let3.constructor === C5) {
|
||||
let3; // never
|
||||
}
|
||||
if (let3.constructor === C6) {
|
||||
let3; // C6
|
||||
}
|
||||
|
||||
// Classes with the same structure
|
||||
class C7 {
|
||||
property1: number
|
||||
}
|
||||
|
||||
class C8 {
|
||||
property1: number;
|
||||
}
|
||||
|
||||
let let4: C8 | string;
|
||||
if (let4.constructor === C7) {
|
||||
let4; // never
|
||||
}
|
||||
if (let4.constructor === C8) {
|
||||
let4; // C8
|
||||
}
|
||||
23
tests/cases/compiler/typeGuardConstructorNarrowAny.ts
Normal file
23
tests/cases/compiler/typeGuardConstructorNarrowAny.ts
Normal file
@ -0,0 +1,23 @@
|
||||
// @target: esnext
|
||||
|
||||
// Narrowing any to primitives
|
||||
let var1: any;
|
||||
|
||||
if (var1.constructor === String) {
|
||||
var1; // String
|
||||
}
|
||||
if (var1.constructor === Number) {
|
||||
var1; // Number
|
||||
}
|
||||
if (var1.constructor === Boolean) {
|
||||
var1; // Boolean
|
||||
}
|
||||
if (var1.constructor === Array) {
|
||||
var1; // any[]
|
||||
}
|
||||
if (var1.constructor === Symbol) {
|
||||
var1; // Symbol
|
||||
}
|
||||
if (var1.constructor === BigInt) {
|
||||
var1; // BigInt
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
// Union of primitives, number, arrays, and C1
|
||||
let var1: number | "hello" | "world" | true | false | number[] | string[];
|
||||
|
||||
if (var1.constructor === Number) {
|
||||
var1; // number
|
||||
}
|
||||
|
||||
if (var1.constructor === String) {
|
||||
var1; // "hello" | "world"
|
||||
}
|
||||
|
||||
if (var1.constructor === Boolean) {
|
||||
var1; // boolean
|
||||
}
|
||||
|
||||
if (var1.constructor === Array) {
|
||||
var1; // number[] | string[]
|
||||
}
|
||||
40
tests/cases/compiler/typeGuardConstructorPrimitiveTypes.ts
Normal file
40
tests/cases/compiler/typeGuardConstructorPrimitiveTypes.ts
Normal file
@ -0,0 +1,40 @@
|
||||
// @target: esnext
|
||||
|
||||
// Narrow a union of primitive types
|
||||
let var1: string | number | boolean | any[] | symbol | bigint;
|
||||
if (var1.constructor === String) {
|
||||
var1; // string
|
||||
}
|
||||
if (var1.constructor === Number) {
|
||||
var1; // number
|
||||
}
|
||||
if (var1.constructor === Boolean) {
|
||||
var1; // boolean
|
||||
}
|
||||
if (var1.constructor === Array) {
|
||||
var1; // any[]
|
||||
}
|
||||
if (var1.constructor === Symbol) {
|
||||
var1; // symbol
|
||||
}
|
||||
if (var1.constructor === BigInt) {
|
||||
var1; // bigint
|
||||
}
|
||||
|
||||
// Narrow a union of primitive object types
|
||||
let var2: String | Number | Boolean | Symbol | BigInt;
|
||||
if (var2.constructor === String) {
|
||||
var2; // String
|
||||
}
|
||||
if (var2.constructor === Number) {
|
||||
var2; // Number
|
||||
}
|
||||
if (var2.constructor === Boolean) {
|
||||
var2; // Boolean
|
||||
}
|
||||
if (var2.constructor === Symbol) {
|
||||
var2; // Symbol
|
||||
}
|
||||
if (var2.constructor === BigInt) {
|
||||
var2; // BigInt
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user