Skip to content

Commit 884c72e

Browse files
authored
Merge pull request #18654 from Microsoft/strictFunctionTypes
Strict function types
2 parents eefe5c9 + c2344e0 commit 884c72e

File tree

23 files changed

+1986
-47
lines changed

23 files changed

+1986
-47
lines changed

src/compiler/checker.ts

Lines changed: 173 additions & 22 deletions
Large diffs are not rendered by default.

src/compiler/commandLineParser.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,13 @@ namespace ts {
269269
category: Diagnostics.Strict_Type_Checking_Options,
270270
description: Diagnostics.Enable_strict_null_checks
271271
},
272+
{
273+
name: "strictFunctionTypes",
274+
type: "boolean",
275+
showInSimplifiedHelpView: true,
276+
category: Diagnostics.Strict_Type_Checking_Options,
277+
description: Diagnostics.Enable_strict_checking_of_function_types
278+
},
272279
{
273280
name: "noImplicitThis",
274281
type: "boolean",

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3314,6 +3314,10 @@
33143314
"category": "Message",
33153315
"code": 6185
33163316
},
3317+
"Enable strict checking of function types.": {
3318+
"category": "Message",
3319+
"code": 6186
3320+
},
33173321
"Variable '{0}' implicitly has an '{1}' type.": {
33183322
"category": "Error",
33193323
"code": 7005

src/compiler/types.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3215,6 +3215,7 @@ namespace ts {
32153215
NonPrimitive = 1 << 24, // intrinsic object type
32163216
/* @internal */
32173217
JsxAttributes = 1 << 25, // Jsx attributes type
3218+
MarkerType = 1 << 26, // Marker type used for variance probing
32183219

32193220
/* @internal */
32203221
Nullable = Undefined | Null,
@@ -3343,10 +3344,21 @@ namespace ts {
33433344
typeArguments?: Type[]; // Type reference type arguments (undefined if none)
33443345
}
33453346

3347+
/* @internal */
3348+
export const enum Variance {
3349+
Invariant = 0, // Neither covariant nor contravariant
3350+
Covariant = 1, // Covariant
3351+
Contravariant = 2, // Contravariant
3352+
Bivariant = 3, // Both covariant and contravariant
3353+
Independent = 4, // Unwitnessed type parameter
3354+
}
3355+
33463356
// Generic class and interface types
33473357
export interface GenericType extends InterfaceType, TypeReference {
33483358
/* @internal */
3349-
instantiations: Map<TypeReference>; // Generic instantiation cache
3359+
instantiations: Map<TypeReference>; // Generic instantiation cache
3360+
/* @internal */
3361+
variances?: Variance[]; // Variance of each type parameter
33503362
}
33513363

33523364
export interface UnionOrIntersectionType extends Type {
@@ -3522,9 +3534,10 @@ namespace ts {
35223534
}
35233535

35243536
export const enum InferencePriority {
3525-
NakedTypeVariable = 1 << 0, // Naked type variable in union or intersection type
3526-
MappedType = 1 << 1, // Reverse inference for mapped type
3527-
ReturnType = 1 << 2, // Inference made from return type of generic function
3537+
Contravariant = 1 << 0, // Inference from contravariant position
3538+
NakedTypeVariable = 1 << 1, // Naked type variable in union or intersection type
3539+
MappedType = 1 << 2, // Reverse inference for mapped type
3540+
ReturnType = 1 << 3, // Inference made from return type of generic function
35283541
}
35293542

35303543
export interface InferenceInfo {
@@ -3707,6 +3720,7 @@ namespace ts {
37073720
sourceMap?: boolean;
37083721
sourceRoot?: string;
37093722
strict?: boolean;
3723+
strictFunctionTypes?: boolean; // Always combine with strict property
37103724
strictNullChecks?: boolean; // Always combine with strict property
37113725
/* @internal */ stripInternal?: boolean;
37123726
suppressExcessPropertyErrors?: boolean;

src/lib/dom.generated.d.ts

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4233,11 +4233,7 @@ interface HTMLBodyElement extends HTMLElement {
42334233
onafterprint: (this: HTMLBodyElement, ev: Event) => any;
42344234
onbeforeprint: (this: HTMLBodyElement, ev: Event) => any;
42354235
onbeforeunload: (this: HTMLBodyElement, ev: BeforeUnloadEvent) => any;
4236-
onblur: (this: HTMLBodyElement, ev: FocusEvent) => any;
4237-
onerror: (this: HTMLBodyElement, ev: ErrorEvent) => any;
4238-
onfocus: (this: HTMLBodyElement, ev: FocusEvent) => any;
42394236
onhashchange: (this: HTMLBodyElement, ev: HashChangeEvent) => any;
4240-
onload: (this: HTMLBodyElement, ev: Event) => any;
42414237
onmessage: (this: HTMLBodyElement, ev: MessageEvent) => any;
42424238
onoffline: (this: HTMLBodyElement, ev: Event) => any;
42434239
ononline: (this: HTMLBodyElement, ev: Event) => any;
@@ -4246,7 +4242,6 @@ interface HTMLBodyElement extends HTMLElement {
42464242
onpageshow: (this: HTMLBodyElement, ev: PageTransitionEvent) => any;
42474243
onpopstate: (this: HTMLBodyElement, ev: PopStateEvent) => any;
42484244
onresize: (this: HTMLBodyElement, ev: UIEvent) => any;
4249-
onscroll: (this: HTMLBodyElement, ev: UIEvent) => any;
42504245
onstorage: (this: HTMLBodyElement, ev: StorageEvent) => any;
42514246
onunload: (this: HTMLBodyElement, ev: Event) => any;
42524247
text: any;
@@ -4901,10 +4896,6 @@ interface HTMLFrameElement extends HTMLElement, GetSVGDocument {
49014896
* Sets or retrieves whether the user can resize the frame.
49024897
*/
49034898
noResize: boolean;
4904-
/**
4905-
* Raised when the object has been completely received from the server.
4906-
*/
4907-
onload: (this: HTMLFrameElement, ev: Event) => any;
49084899
/**
49094900
* Sets or retrieves whether the frame can be scrolled.
49104901
*/
@@ -4970,17 +4961,10 @@ interface HTMLFrameSetElement extends HTMLElement {
49704961
onafterprint: (this: HTMLFrameSetElement, ev: Event) => any;
49714962
onbeforeprint: (this: HTMLFrameSetElement, ev: Event) => any;
49724963
onbeforeunload: (this: HTMLFrameSetElement, ev: BeforeUnloadEvent) => any;
4973-
/**
4974-
* Fires when the object loses the input focus.
4975-
*/
4976-
onblur: (this: HTMLFrameSetElement, ev: FocusEvent) => any;
4977-
onerror: (this: HTMLFrameSetElement, ev: ErrorEvent) => any;
49784964
/**
49794965
* Fires when the object receives focus.
49804966
*/
4981-
onfocus: (this: HTMLFrameSetElement, ev: FocusEvent) => any;
49824967
onhashchange: (this: HTMLFrameSetElement, ev: HashChangeEvent) => any;
4983-
onload: (this: HTMLFrameSetElement, ev: Event) => any;
49844968
onmessage: (this: HTMLFrameSetElement, ev: MessageEvent) => any;
49854969
onoffline: (this: HTMLFrameSetElement, ev: Event) => any;
49864970
ononline: (this: HTMLFrameSetElement, ev: Event) => any;
@@ -4989,7 +4973,6 @@ interface HTMLFrameSetElement extends HTMLElement {
49894973
onpageshow: (this: HTMLFrameSetElement, ev: PageTransitionEvent) => any;
49904974
onpopstate: (this: HTMLFrameSetElement, ev: PopStateEvent) => any;
49914975
onresize: (this: HTMLFrameSetElement, ev: UIEvent) => any;
4992-
onscroll: (this: HTMLFrameSetElement, ev: UIEvent) => any;
49934976
onstorage: (this: HTMLFrameSetElement, ev: StorageEvent) => any;
49944977
onunload: (this: HTMLFrameSetElement, ev: Event) => any;
49954978
/**
@@ -5125,10 +5108,7 @@ interface HTMLIFrameElement extends HTMLElement, GetSVGDocument {
51255108
* Sets or retrieves whether the user can resize the frame.
51265109
*/
51275110
noResize: boolean;
5128-
/**
5129-
* Raised when the object has been completely received from the server.
5130-
*/
5131-
onload: (this: HTMLIFrameElement, ev: Event) => any;
5111+
51325112
readonly sandbox: DOMSettableTokenList;
51335113
/**
51345114
* Sets or retrieves whether the frame can be scrolled.

tests/baselines/reference/fuzzy.errors.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ tests/cases/compiler/fuzzy.ts(21,13): error TS2322: Type '{ anything: number; on
44
Types of property 'oneI' are incompatible.
55
Type 'this' is not assignable to type 'I'.
66
Type 'C' is not assignable to type 'I'.
7+
Property 'alsoWorks' is missing in type 'C'.
78
tests/cases/compiler/fuzzy.ts(25,20): error TS2352: Type '{ oneI: this; }' cannot be converted to type 'R'.
89
Property 'anything' is missing in type '{ oneI: this; }'.
910

@@ -38,6 +39,7 @@ tests/cases/compiler/fuzzy.ts(25,20): error TS2352: Type '{ oneI: this; }' canno
3839
!!! error TS2322: Types of property 'oneI' are incompatible.
3940
!!! error TS2322: Type 'this' is not assignable to type 'I'.
4041
!!! error TS2322: Type 'C' is not assignable to type 'I'.
42+
!!! error TS2322: Property 'alsoWorks' is missing in type 'C'.
4143
}
4244

4345
worksToo():R {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//// [strictFunctionTypes1.ts]
2+
declare function f1<T>(f1: (x: T) => void, f2: (x: T) => void): (x: T) => void;
3+
declare function f2<T>(obj: T, f1: (x: T) => void, f2: (x: T) => void): T;
4+
declare function f3<T>(obj: T, f1: (x: T) => void, f2: (f: (x: T) => void) => void): T;
5+
6+
interface Func<T> { (x: T): void }
7+
8+
declare function f4<T>(f1: Func<T>, f2: Func<T>): Func<T>;
9+
10+
declare function fo(x: Object): void;
11+
declare function fs(x: string): void;
12+
declare function fx(f: (x: "def") => void): void;
13+
14+
const x1 = f1(fo, fs); // (x: string) => void
15+
const x2 = f2("abc", fo, fs); // "abc"
16+
const x3 = f3("abc", fo, fx); // "abc" | "def"
17+
const x4 = f4(fo, fs); // Func<string>
18+
19+
20+
//// [strictFunctionTypes1.js]
21+
"use strict";
22+
var x1 = f1(fo, fs); // (x: string) => void
23+
var x2 = f2("abc", fo, fs); // "abc"
24+
var x3 = f3("abc", fo, fx); // "abc" | "def"
25+
var x4 = f4(fo, fs); // Func<string>
26+
27+
28+
//// [strictFunctionTypes1.d.ts]
29+
declare function f1<T>(f1: (x: T) => void, f2: (x: T) => void): (x: T) => void;
30+
declare function f2<T>(obj: T, f1: (x: T) => void, f2: (x: T) => void): T;
31+
declare function f3<T>(obj: T, f1: (x: T) => void, f2: (f: (x: T) => void) => void): T;
32+
interface Func<T> {
33+
(x: T): void;
34+
}
35+
declare function f4<T>(f1: Func<T>, f2: Func<T>): Func<T>;
36+
declare function fo(x: Object): void;
37+
declare function fs(x: string): void;
38+
declare function fx(f: (x: "def") => void): void;
39+
declare const x1: (x: string) => void;
40+
declare const x2 = "abc";
41+
declare const x3: string;
42+
declare const x4: Func<string>;
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
=== tests/cases/compiler/strictFunctionTypes1.ts ===
2+
declare function f1<T>(f1: (x: T) => void, f2: (x: T) => void): (x: T) => void;
3+
>f1 : Symbol(f1, Decl(strictFunctionTypes1.ts, 0, 0))
4+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 0, 20))
5+
>f1 : Symbol(f1, Decl(strictFunctionTypes1.ts, 0, 23))
6+
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 0, 28))
7+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 0, 20))
8+
>f2 : Symbol(f2, Decl(strictFunctionTypes1.ts, 0, 42))
9+
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 0, 48))
10+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 0, 20))
11+
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 0, 65))
12+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 0, 20))
13+
14+
declare function f2<T>(obj: T, f1: (x: T) => void, f2: (x: T) => void): T;
15+
>f2 : Symbol(f2, Decl(strictFunctionTypes1.ts, 0, 79))
16+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 1, 20))
17+
>obj : Symbol(obj, Decl(strictFunctionTypes1.ts, 1, 23))
18+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 1, 20))
19+
>f1 : Symbol(f1, Decl(strictFunctionTypes1.ts, 1, 30))
20+
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 1, 36))
21+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 1, 20))
22+
>f2 : Symbol(f2, Decl(strictFunctionTypes1.ts, 1, 50))
23+
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 1, 56))
24+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 1, 20))
25+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 1, 20))
26+
27+
declare function f3<T>(obj: T, f1: (x: T) => void, f2: (f: (x: T) => void) => void): T;
28+
>f3 : Symbol(f3, Decl(strictFunctionTypes1.ts, 1, 74))
29+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 2, 20))
30+
>obj : Symbol(obj, Decl(strictFunctionTypes1.ts, 2, 23))
31+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 2, 20))
32+
>f1 : Symbol(f1, Decl(strictFunctionTypes1.ts, 2, 30))
33+
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 2, 36))
34+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 2, 20))
35+
>f2 : Symbol(f2, Decl(strictFunctionTypes1.ts, 2, 50))
36+
>f : Symbol(f, Decl(strictFunctionTypes1.ts, 2, 56))
37+
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 2, 60))
38+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 2, 20))
39+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 2, 20))
40+
41+
interface Func<T> { (x: T): void }
42+
>Func : Symbol(Func, Decl(strictFunctionTypes1.ts, 2, 87))
43+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 4, 15))
44+
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 4, 21))
45+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 4, 15))
46+
47+
declare function f4<T>(f1: Func<T>, f2: Func<T>): Func<T>;
48+
>f4 : Symbol(f4, Decl(strictFunctionTypes1.ts, 4, 34))
49+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 6, 20))
50+
>f1 : Symbol(f1, Decl(strictFunctionTypes1.ts, 6, 23))
51+
>Func : Symbol(Func, Decl(strictFunctionTypes1.ts, 2, 87))
52+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 6, 20))
53+
>f2 : Symbol(f2, Decl(strictFunctionTypes1.ts, 6, 35))
54+
>Func : Symbol(Func, Decl(strictFunctionTypes1.ts, 2, 87))
55+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 6, 20))
56+
>Func : Symbol(Func, Decl(strictFunctionTypes1.ts, 2, 87))
57+
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 6, 20))
58+
59+
declare function fo(x: Object): void;
60+
>fo : Symbol(fo, Decl(strictFunctionTypes1.ts, 6, 58))
61+
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 8, 20))
62+
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
63+
64+
declare function fs(x: string): void;
65+
>fs : Symbol(fs, Decl(strictFunctionTypes1.ts, 8, 37))
66+
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 9, 20))
67+
68+
declare function fx(f: (x: "def") => void): void;
69+
>fx : Symbol(fx, Decl(strictFunctionTypes1.ts, 9, 37))
70+
>f : Symbol(f, Decl(strictFunctionTypes1.ts, 10, 20))
71+
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 10, 24))
72+
73+
const x1 = f1(fo, fs); // (x: string) => void
74+
>x1 : Symbol(x1, Decl(strictFunctionTypes1.ts, 12, 5))
75+
>f1 : Symbol(f1, Decl(strictFunctionTypes1.ts, 0, 0))
76+
>fo : Symbol(fo, Decl(strictFunctionTypes1.ts, 6, 58))
77+
>fs : Symbol(fs, Decl(strictFunctionTypes1.ts, 8, 37))
78+
79+
const x2 = f2("abc", fo, fs); // "abc"
80+
>x2 : Symbol(x2, Decl(strictFunctionTypes1.ts, 13, 5))
81+
>f2 : Symbol(f2, Decl(strictFunctionTypes1.ts, 0, 79))
82+
>fo : Symbol(fo, Decl(strictFunctionTypes1.ts, 6, 58))
83+
>fs : Symbol(fs, Decl(strictFunctionTypes1.ts, 8, 37))
84+
85+
const x3 = f3("abc", fo, fx); // "abc" | "def"
86+
>x3 : Symbol(x3, Decl(strictFunctionTypes1.ts, 14, 5))
87+
>f3 : Symbol(f3, Decl(strictFunctionTypes1.ts, 1, 74))
88+
>fo : Symbol(fo, Decl(strictFunctionTypes1.ts, 6, 58))
89+
>fx : Symbol(fx, Decl(strictFunctionTypes1.ts, 9, 37))
90+
91+
const x4 = f4(fo, fs); // Func<string>
92+
>x4 : Symbol(x4, Decl(strictFunctionTypes1.ts, 15, 5))
93+
>f4 : Symbol(f4, Decl(strictFunctionTypes1.ts, 4, 34))
94+
>fo : Symbol(fo, Decl(strictFunctionTypes1.ts, 6, 58))
95+
>fs : Symbol(fs, Decl(strictFunctionTypes1.ts, 8, 37))
96+

0 commit comments

Comments
 (0)