Skip to content

Commit 4353865

Browse files
Merge pull request #7067 from Microsoft/removePredicateTypinessToMaster
(Porting to 'master') Remove notion of predicates as types, move predicates back to signatures
2 parents fc63b5f + e29be4b commit 4353865

File tree

60 files changed

+1115
-927
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1115
-927
lines changed

Diff for: src/compiler/checker.ts

+120-133
Large diffs are not rendered by default.

Diff for: src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,10 @@
723723
"category": "Error",
724724
"code": 1227
725725
},
726+
"A type predicate is only allowed in return type position for functions and methods.": {
727+
"category": "Error",
728+
"code": 1228
729+
},
726730
"A type predicate cannot reference a rest parameter.": {
727731
"category": "Error",
728732
"code": 1229

Diff for: src/compiler/parser.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1937,7 +1937,7 @@ namespace ts {
19371937
return finishNode(node);
19381938
}
19391939

1940-
function parseTypePredicate(lhs: Identifier | ThisTypeNode): TypePredicateNode {
1940+
function parseThisTypePredicate(lhs: ThisTypeNode): TypePredicateNode {
19411941
nextToken();
19421942
const node = createNode(SyntaxKind.TypePredicate, lhs.pos) as TypePredicateNode;
19431943
node.parameterName = lhs;
@@ -2362,7 +2362,7 @@ namespace ts {
23622362
case SyntaxKind.ThisKeyword: {
23632363
const thisKeyword = parseThisTypeNode();
23642364
if (token === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) {
2365-
return parseTypePredicate(thisKeyword);
2365+
return parseThisTypePredicate(thisKeyword);
23662366
}
23672367
else {
23682368
return thisKeyword;

Diff for: src/compiler/types.ts

+9-10
Original file line numberDiff line numberDiff line change
@@ -1748,6 +1748,7 @@ namespace ts {
17481748
buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void;
17491749
buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
17501750
buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
1751+
buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
17511752
buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
17521753
buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
17531754
buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
@@ -1813,22 +1814,24 @@ namespace ts {
18131814
Identifier
18141815
}
18151816

1816-
export interface TypePredicate {
1817+
export interface TypePredicateBase {
18171818
kind: TypePredicateKind;
18181819
type: Type;
18191820
}
18201821

18211822
// @kind (TypePredicateKind.This)
1822-
export interface ThisTypePredicate extends TypePredicate {
1823+
export interface ThisTypePredicate extends TypePredicateBase {
18231824
_thisTypePredicateBrand: any;
18241825
}
18251826

18261827
// @kind (TypePredicateKind.Identifier)
1827-
export interface IdentifierTypePredicate extends TypePredicate {
1828+
export interface IdentifierTypePredicate extends TypePredicateBase {
18281829
parameterName: string;
18291830
parameterIndex: number;
18301831
}
18311832

1833+
export type TypePredicate = IdentifierTypePredicate | ThisTypePredicate;
1834+
18321835
/* @internal */
18331836
export type AnyImportSyntax = ImportDeclaration | ImportEqualsDeclaration;
18341837

@@ -2095,7 +2098,6 @@ namespace ts {
20952098
ESSymbol = 0x01000000, // Type of symbol primitive introduced in ES6
20962099
ThisType = 0x02000000, // This type
20972100
ObjectLiteralPatternWithComputedProperties = 0x04000000, // Object literal type implied by binding pattern has computed properties
2098-
PredicateType = 0x08000000, // Predicate types are also Boolean types, but should not be considered Intrinsics - there's no way to capture this with flags
20992101

21002102
/* @internal */
21012103
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
@@ -2107,7 +2109,7 @@ namespace ts {
21072109
UnionOrIntersection = Union | Intersection,
21082110
StructuredType = ObjectType | Union | Intersection,
21092111
/* @internal */
2110-
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral | PredicateType,
2112+
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral,
21112113
/* @internal */
21122114
PropagatingFlags = ContainsUndefinedOrNull | ContainsObjectLiteral | ContainsAnyFunctionType
21132115
}
@@ -2128,11 +2130,6 @@ namespace ts {
21282130
intrinsicName: string; // Name of intrinsic type
21292131
}
21302132

2131-
// Predicate types (TypeFlags.Predicate)
2132-
export interface PredicateType extends Type {
2133-
predicate: ThisTypePredicate | IdentifierTypePredicate;
2134-
}
2135-
21362133
// String literal types (TypeFlags.StringLiteral)
21372134
export interface StringLiteralType extends Type {
21382135
text: string; // Text of string literal
@@ -2267,6 +2264,8 @@ namespace ts {
22672264
erasedSignatureCache?: Signature; // Erased version of signature (deferred)
22682265
/* @internal */
22692266
isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
2267+
/* @internal */
2268+
typePredicate?: TypePredicate;
22702269
}
22712270

22722271
export const enum IndexKind {

Diff for: src/compiler/utilities.ts

+4
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,10 @@ namespace ts {
748748
return predicate && predicate.kind === TypePredicateKind.Identifier;
749749
}
750750

751+
export function isThisTypePredicate(predicate: TypePredicate): predicate is ThisTypePredicate {
752+
return predicate && predicate.kind === TypePredicateKind.This;
753+
}
754+
751755
export function getContainingFunction(node: Node): FunctionLikeDeclaration {
752756
while (true) {
753757
node = node.parent;

Diff for: tests/baselines/reference/arrayBufferIsViewNarrowsType.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ var obj: Object;
44
>Object : Object
55

66
if (ArrayBuffer.isView(obj)) {
7-
>ArrayBuffer.isView(obj) : arg is ArrayBufferView
7+
>ArrayBuffer.isView(obj) : boolean
88
>ArrayBuffer.isView : (arg: any) => arg is ArrayBufferView
99
>ArrayBuffer : ArrayBufferConstructor
1010
>isView : (arg: any) => arg is ArrayBufferView
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//// [declarationEmitIdentifierPredicates01.ts]
2+
3+
export function f(x: any): x is number {
4+
return typeof x === "number";
5+
}
6+
7+
//// [declarationEmitIdentifierPredicates01.js]
8+
"use strict";
9+
function f(x) {
10+
return typeof x === "number";
11+
}
12+
exports.f = f;
13+
14+
15+
//// [declarationEmitIdentifierPredicates01.d.ts]
16+
export declare function f(x: any): x is number;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
=== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitIdentifierPredicates01.ts ===
2+
3+
export function f(x: any): x is number {
4+
>f : Symbol(f, Decl(declarationEmitIdentifierPredicates01.ts, 0, 0))
5+
>x : Symbol(x, Decl(declarationEmitIdentifierPredicates01.ts, 1, 18))
6+
>x : Symbol(x, Decl(declarationEmitIdentifierPredicates01.ts, 1, 18))
7+
8+
return typeof x === "number";
9+
>x : Symbol(x, Decl(declarationEmitIdentifierPredicates01.ts, 1, 18))
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
=== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitIdentifierPredicates01.ts ===
2+
3+
export function f(x: any): x is number {
4+
>f : (x: any) => x is number
5+
>x : any
6+
>x : any
7+
8+
return typeof x === "number";
9+
>typeof x === "number" : boolean
10+
>typeof x : string
11+
>x : any
12+
>"number" : string
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
tests/cases/conformance/declarationEmit/typePredicates/declarationEmitIdentifierPredicatesWithPrivateName01.ts(6,33): error TS4060: Return type of exported function has or is using private name 'I'.
2+
3+
4+
==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitIdentifierPredicatesWithPrivateName01.ts (1 errors) ====
5+
6+
interface I {
7+
a: number;
8+
}
9+
10+
export function f(x: any): x is I {
11+
~
12+
!!! error TS4060: Return type of exported function has or is using private name 'I'.
13+
return typeof x.a === "number";
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//// [declarationEmitIdentifierPredicatesWithPrivateName01.ts]
2+
3+
interface I {
4+
a: number;
5+
}
6+
7+
export function f(x: any): x is I {
8+
return typeof x.a === "number";
9+
}
10+
11+
//// [declarationEmitIdentifierPredicatesWithPrivateName01.js]
12+
"use strict";
13+
function f(x) {
14+
return typeof x.a === "number";
15+
}
16+
exports.f = f;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//// [declarationEmitThisPredicates01.ts]
2+
3+
export class C {
4+
m(): this is D {
5+
return this instanceof D;
6+
}
7+
}
8+
9+
export class D extends C {
10+
}
11+
12+
//// [declarationEmitThisPredicates01.js]
13+
"use strict";
14+
var __extends = (this && this.__extends) || function (d, b) {
15+
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
16+
function __() { this.constructor = d; }
17+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
18+
};
19+
var C = (function () {
20+
function C() {
21+
}
22+
C.prototype.m = function () {
23+
return this instanceof D;
24+
};
25+
return C;
26+
}());
27+
exports.C = C;
28+
var D = (function (_super) {
29+
__extends(D, _super);
30+
function D() {
31+
_super.apply(this, arguments);
32+
}
33+
return D;
34+
}(C));
35+
exports.D = D;
36+
37+
38+
//// [declarationEmitThisPredicates01.d.ts]
39+
export declare class C {
40+
m(): this is D;
41+
}
42+
export declare class D extends C {
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
=== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates01.ts ===
2+
3+
export class C {
4+
>C : Symbol(C, Decl(declarationEmitThisPredicates01.ts, 0, 0))
5+
6+
m(): this is D {
7+
>m : Symbol(m, Decl(declarationEmitThisPredicates01.ts, 1, 16))
8+
>D : Symbol(D, Decl(declarationEmitThisPredicates01.ts, 5, 1))
9+
10+
return this instanceof D;
11+
>this : Symbol(C, Decl(declarationEmitThisPredicates01.ts, 0, 0))
12+
>D : Symbol(D, Decl(declarationEmitThisPredicates01.ts, 5, 1))
13+
}
14+
}
15+
16+
export class D extends C {
17+
>D : Symbol(D, Decl(declarationEmitThisPredicates01.ts, 5, 1))
18+
>C : Symbol(C, Decl(declarationEmitThisPredicates01.ts, 0, 0))
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
=== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates01.ts ===
2+
3+
export class C {
4+
>C : C
5+
6+
m(): this is D {
7+
>m : () => this is D
8+
>D : D
9+
10+
return this instanceof D;
11+
>this instanceof D : boolean
12+
>this : this
13+
>D : typeof D
14+
}
15+
}
16+
17+
export class D extends C {
18+
>D : D
19+
>C : C
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts(9,10): error TS2526: A 'this' type is available only in a non-static member of a class or interface.
2+
3+
4+
==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts (1 errors) ====
5+
6+
export interface Foo {
7+
a: string;
8+
b: number;
9+
c: boolean;
10+
}
11+
12+
export const obj = {
13+
m(): this is Foo {
14+
~~~~
15+
!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface.
16+
let dis = this as Foo;
17+
return dis.a != null && dis.b != null && dis.c != null;
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//// [declarationEmitThisPredicates02.ts]
2+
3+
export interface Foo {
4+
a: string;
5+
b: number;
6+
c: boolean;
7+
}
8+
9+
export const obj = {
10+
m(): this is Foo {
11+
let dis = this as Foo;
12+
return dis.a != null && dis.b != null && dis.c != null;
13+
}
14+
}
15+
16+
//// [declarationEmitThisPredicates02.js]
17+
"use strict";
18+
exports.obj = {
19+
m: function () {
20+
var dis = this;
21+
return dis.a != null && dis.b != null && dis.c != null;
22+
}
23+
};
24+
25+
26+
//// [declarationEmitThisPredicates02.d.ts]
27+
export interface Foo {
28+
a: string;
29+
b: number;
30+
c: boolean;
31+
}
32+
export declare const obj: {
33+
m(): this is Foo;
34+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName01.ts(3,18): error TS4055: Return type of public method from exported class has or is using private name 'D'.
2+
3+
4+
==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName01.ts (1 errors) ====
5+
6+
export class C {
7+
m(): this is D {
8+
~
9+
!!! error TS4055: Return type of public method from exported class has or is using private name 'D'.
10+
return this instanceof D;
11+
}
12+
}
13+
14+
class D extends C {
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//// [declarationEmitThisPredicatesWithPrivateName01.ts]
2+
3+
export class C {
4+
m(): this is D {
5+
return this instanceof D;
6+
}
7+
}
8+
9+
class D extends C {
10+
}
11+
12+
//// [declarationEmitThisPredicatesWithPrivateName01.js]
13+
"use strict";
14+
var __extends = (this && this.__extends) || function (d, b) {
15+
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
16+
function __() { this.constructor = d; }
17+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
18+
};
19+
var C = (function () {
20+
function C() {
21+
}
22+
C.prototype.m = function () {
23+
return this instanceof D;
24+
};
25+
return C;
26+
}());
27+
exports.C = C;
28+
var D = (function (_super) {
29+
__extends(D, _super);
30+
function D() {
31+
_super.apply(this, arguments);
32+
}
33+
return D;
34+
}(C));

0 commit comments

Comments
 (0)