Skip to content

Commit

Permalink
Merge pull request #18654 from Microsoft/strictFunctionTypes
Browse files Browse the repository at this point in the history
Strict function types
  • Loading branch information
ahejlsberg committed Oct 2, 2017
2 parents eefe5c9 + c2344e0 commit 884c72e
Show file tree
Hide file tree
Showing 23 changed files with 1,986 additions and 47 deletions.
195 changes: 173 additions & 22 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,13 @@ namespace ts {
category: Diagnostics.Strict_Type_Checking_Options,
description: Diagnostics.Enable_strict_null_checks
},
{
name: "strictFunctionTypes",
type: "boolean",
showInSimplifiedHelpView: true,
category: Diagnostics.Strict_Type_Checking_Options,
description: Diagnostics.Enable_strict_checking_of_function_types
},
{
name: "noImplicitThis",
type: "boolean",
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3314,6 +3314,10 @@
"category": "Message",
"code": 6185
},
"Enable strict checking of function types.": {
"category": "Message",
"code": 6186
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005
Expand Down
22 changes: 18 additions & 4 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3215,6 +3215,7 @@ namespace ts {
NonPrimitive = 1 << 24, // intrinsic object type
/* @internal */
JsxAttributes = 1 << 25, // Jsx attributes type
MarkerType = 1 << 26, // Marker type used for variance probing

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

/* @internal */
export const enum Variance {
Invariant = 0, // Neither covariant nor contravariant
Covariant = 1, // Covariant
Contravariant = 2, // Contravariant
Bivariant = 3, // Both covariant and contravariant
Independent = 4, // Unwitnessed type parameter
}

// Generic class and interface types
export interface GenericType extends InterfaceType, TypeReference {
/* @internal */
instantiations: Map<TypeReference>; // Generic instantiation cache
instantiations: Map<TypeReference>; // Generic instantiation cache
/* @internal */
variances?: Variance[]; // Variance of each type parameter
}

export interface UnionOrIntersectionType extends Type {
Expand Down Expand Up @@ -3522,9 +3534,10 @@ namespace ts {
}

export const enum InferencePriority {
NakedTypeVariable = 1 << 0, // Naked type variable in union or intersection type
MappedType = 1 << 1, // Reverse inference for mapped type
ReturnType = 1 << 2, // Inference made from return type of generic function
Contravariant = 1 << 0, // Inference from contravariant position
NakedTypeVariable = 1 << 1, // Naked type variable in union or intersection type
MappedType = 1 << 2, // Reverse inference for mapped type
ReturnType = 1 << 3, // Inference made from return type of generic function
}

export interface InferenceInfo {
Expand Down Expand Up @@ -3707,6 +3720,7 @@ namespace ts {
sourceMap?: boolean;
sourceRoot?: string;
strict?: boolean;
strictFunctionTypes?: boolean; // Always combine with strict property
strictNullChecks?: boolean; // Always combine with strict property
/* @internal */ stripInternal?: boolean;
suppressExcessPropertyErrors?: boolean;
Expand Down
22 changes: 1 addition & 21 deletions src/lib/dom.generated.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4233,11 +4233,7 @@ interface HTMLBodyElement extends HTMLElement {
onafterprint: (this: HTMLBodyElement, ev: Event) => any;
onbeforeprint: (this: HTMLBodyElement, ev: Event) => any;
onbeforeunload: (this: HTMLBodyElement, ev: BeforeUnloadEvent) => any;
onblur: (this: HTMLBodyElement, ev: FocusEvent) => any;
onerror: (this: HTMLBodyElement, ev: ErrorEvent) => any;
onfocus: (this: HTMLBodyElement, ev: FocusEvent) => any;
onhashchange: (this: HTMLBodyElement, ev: HashChangeEvent) => any;
onload: (this: HTMLBodyElement, ev: Event) => any;
onmessage: (this: HTMLBodyElement, ev: MessageEvent) => any;
onoffline: (this: HTMLBodyElement, ev: Event) => any;
ononline: (this: HTMLBodyElement, ev: Event) => any;
Expand All @@ -4246,7 +4242,6 @@ interface HTMLBodyElement extends HTMLElement {
onpageshow: (this: HTMLBodyElement, ev: PageTransitionEvent) => any;
onpopstate: (this: HTMLBodyElement, ev: PopStateEvent) => any;
onresize: (this: HTMLBodyElement, ev: UIEvent) => any;
onscroll: (this: HTMLBodyElement, ev: UIEvent) => any;
onstorage: (this: HTMLBodyElement, ev: StorageEvent) => any;
onunload: (this: HTMLBodyElement, ev: Event) => any;
text: any;
Expand Down Expand Up @@ -4901,10 +4896,6 @@ interface HTMLFrameElement extends HTMLElement, GetSVGDocument {
* Sets or retrieves whether the user can resize the frame.
*/
noResize: boolean;
/**
* Raised when the object has been completely received from the server.
*/
onload: (this: HTMLFrameElement, ev: Event) => any;
/**
* Sets or retrieves whether the frame can be scrolled.
*/
Expand Down Expand Up @@ -4970,17 +4961,10 @@ interface HTMLFrameSetElement extends HTMLElement {
onafterprint: (this: HTMLFrameSetElement, ev: Event) => any;
onbeforeprint: (this: HTMLFrameSetElement, ev: Event) => any;
onbeforeunload: (this: HTMLFrameSetElement, ev: BeforeUnloadEvent) => any;
/**
* Fires when the object loses the input focus.
*/
onblur: (this: HTMLFrameSetElement, ev: FocusEvent) => any;
onerror: (this: HTMLFrameSetElement, ev: ErrorEvent) => any;
/**
* Fires when the object receives focus.
*/
onfocus: (this: HTMLFrameSetElement, ev: FocusEvent) => any;
onhashchange: (this: HTMLFrameSetElement, ev: HashChangeEvent) => any;
onload: (this: HTMLFrameSetElement, ev: Event) => any;
onmessage: (this: HTMLFrameSetElement, ev: MessageEvent) => any;
onoffline: (this: HTMLFrameSetElement, ev: Event) => any;
ononline: (this: HTMLFrameSetElement, ev: Event) => any;
Expand All @@ -4989,7 +4973,6 @@ interface HTMLFrameSetElement extends HTMLElement {
onpageshow: (this: HTMLFrameSetElement, ev: PageTransitionEvent) => any;
onpopstate: (this: HTMLFrameSetElement, ev: PopStateEvent) => any;
onresize: (this: HTMLFrameSetElement, ev: UIEvent) => any;
onscroll: (this: HTMLFrameSetElement, ev: UIEvent) => any;
onstorage: (this: HTMLFrameSetElement, ev: StorageEvent) => any;
onunload: (this: HTMLFrameSetElement, ev: Event) => any;
/**
Expand Down Expand Up @@ -5125,10 +5108,7 @@ interface HTMLIFrameElement extends HTMLElement, GetSVGDocument {
* Sets or retrieves whether the user can resize the frame.
*/
noResize: boolean;
/**
* Raised when the object has been completely received from the server.
*/
onload: (this: HTMLIFrameElement, ev: Event) => any;

readonly sandbox: DOMSettableTokenList;
/**
* Sets or retrieves whether the frame can be scrolled.
Expand Down
2 changes: 2 additions & 0 deletions tests/baselines/reference/fuzzy.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ tests/cases/compiler/fuzzy.ts(21,13): error TS2322: Type '{ anything: number; on
Types of property 'oneI' are incompatible.
Type 'this' is not assignable to type 'I'.
Type 'C' is not assignable to type 'I'.
Property 'alsoWorks' is missing in type 'C'.
tests/cases/compiler/fuzzy.ts(25,20): error TS2352: Type '{ oneI: this; }' cannot be converted to type 'R'.
Property 'anything' is missing in type '{ oneI: this; }'.

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

worksToo():R {
Expand Down
42 changes: 42 additions & 0 deletions tests/baselines/reference/strictFunctionTypes1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//// [strictFunctionTypes1.ts]
declare function f1<T>(f1: (x: T) => void, f2: (x: T) => void): (x: T) => void;
declare function f2<T>(obj: T, f1: (x: T) => void, f2: (x: T) => void): T;
declare function f3<T>(obj: T, f1: (x: T) => void, f2: (f: (x: T) => void) => void): T;

interface Func<T> { (x: T): void }

declare function f4<T>(f1: Func<T>, f2: Func<T>): Func<T>;

declare function fo(x: Object): void;
declare function fs(x: string): void;
declare function fx(f: (x: "def") => void): void;

const x1 = f1(fo, fs); // (x: string) => void
const x2 = f2("abc", fo, fs); // "abc"
const x3 = f3("abc", fo, fx); // "abc" | "def"
const x4 = f4(fo, fs); // Func<string>


//// [strictFunctionTypes1.js]
"use strict";
var x1 = f1(fo, fs); // (x: string) => void
var x2 = f2("abc", fo, fs); // "abc"
var x3 = f3("abc", fo, fx); // "abc" | "def"
var x4 = f4(fo, fs); // Func<string>


//// [strictFunctionTypes1.d.ts]
declare function f1<T>(f1: (x: T) => void, f2: (x: T) => void): (x: T) => void;
declare function f2<T>(obj: T, f1: (x: T) => void, f2: (x: T) => void): T;
declare function f3<T>(obj: T, f1: (x: T) => void, f2: (f: (x: T) => void) => void): T;
interface Func<T> {
(x: T): void;
}
declare function f4<T>(f1: Func<T>, f2: Func<T>): Func<T>;
declare function fo(x: Object): void;
declare function fs(x: string): void;
declare function fx(f: (x: "def") => void): void;
declare const x1: (x: string) => void;
declare const x2 = "abc";
declare const x3: string;
declare const x4: Func<string>;
96 changes: 96 additions & 0 deletions tests/baselines/reference/strictFunctionTypes1.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
=== tests/cases/compiler/strictFunctionTypes1.ts ===
declare function f1<T>(f1: (x: T) => void, f2: (x: T) => void): (x: T) => void;
>f1 : Symbol(f1, Decl(strictFunctionTypes1.ts, 0, 0))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 0, 20))
>f1 : Symbol(f1, Decl(strictFunctionTypes1.ts, 0, 23))
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 0, 28))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 0, 20))
>f2 : Symbol(f2, Decl(strictFunctionTypes1.ts, 0, 42))
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 0, 48))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 0, 20))
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 0, 65))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 0, 20))

declare function f2<T>(obj: T, f1: (x: T) => void, f2: (x: T) => void): T;
>f2 : Symbol(f2, Decl(strictFunctionTypes1.ts, 0, 79))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 1, 20))
>obj : Symbol(obj, Decl(strictFunctionTypes1.ts, 1, 23))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 1, 20))
>f1 : Symbol(f1, Decl(strictFunctionTypes1.ts, 1, 30))
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 1, 36))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 1, 20))
>f2 : Symbol(f2, Decl(strictFunctionTypes1.ts, 1, 50))
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 1, 56))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 1, 20))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 1, 20))

declare function f3<T>(obj: T, f1: (x: T) => void, f2: (f: (x: T) => void) => void): T;
>f3 : Symbol(f3, Decl(strictFunctionTypes1.ts, 1, 74))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 2, 20))
>obj : Symbol(obj, Decl(strictFunctionTypes1.ts, 2, 23))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 2, 20))
>f1 : Symbol(f1, Decl(strictFunctionTypes1.ts, 2, 30))
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 2, 36))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 2, 20))
>f2 : Symbol(f2, Decl(strictFunctionTypes1.ts, 2, 50))
>f : Symbol(f, Decl(strictFunctionTypes1.ts, 2, 56))
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 2, 60))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 2, 20))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 2, 20))

interface Func<T> { (x: T): void }
>Func : Symbol(Func, Decl(strictFunctionTypes1.ts, 2, 87))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 4, 15))
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 4, 21))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 4, 15))

declare function f4<T>(f1: Func<T>, f2: Func<T>): Func<T>;
>f4 : Symbol(f4, Decl(strictFunctionTypes1.ts, 4, 34))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 6, 20))
>f1 : Symbol(f1, Decl(strictFunctionTypes1.ts, 6, 23))
>Func : Symbol(Func, Decl(strictFunctionTypes1.ts, 2, 87))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 6, 20))
>f2 : Symbol(f2, Decl(strictFunctionTypes1.ts, 6, 35))
>Func : Symbol(Func, Decl(strictFunctionTypes1.ts, 2, 87))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 6, 20))
>Func : Symbol(Func, Decl(strictFunctionTypes1.ts, 2, 87))
>T : Symbol(T, Decl(strictFunctionTypes1.ts, 6, 20))

declare function fo(x: Object): void;
>fo : Symbol(fo, Decl(strictFunctionTypes1.ts, 6, 58))
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 8, 20))
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))

declare function fs(x: string): void;
>fs : Symbol(fs, Decl(strictFunctionTypes1.ts, 8, 37))
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 9, 20))

declare function fx(f: (x: "def") => void): void;
>fx : Symbol(fx, Decl(strictFunctionTypes1.ts, 9, 37))
>f : Symbol(f, Decl(strictFunctionTypes1.ts, 10, 20))
>x : Symbol(x, Decl(strictFunctionTypes1.ts, 10, 24))

const x1 = f1(fo, fs); // (x: string) => void
>x1 : Symbol(x1, Decl(strictFunctionTypes1.ts, 12, 5))
>f1 : Symbol(f1, Decl(strictFunctionTypes1.ts, 0, 0))
>fo : Symbol(fo, Decl(strictFunctionTypes1.ts, 6, 58))
>fs : Symbol(fs, Decl(strictFunctionTypes1.ts, 8, 37))

const x2 = f2("abc", fo, fs); // "abc"
>x2 : Symbol(x2, Decl(strictFunctionTypes1.ts, 13, 5))
>f2 : Symbol(f2, Decl(strictFunctionTypes1.ts, 0, 79))
>fo : Symbol(fo, Decl(strictFunctionTypes1.ts, 6, 58))
>fs : Symbol(fs, Decl(strictFunctionTypes1.ts, 8, 37))

const x3 = f3("abc", fo, fx); // "abc" | "def"
>x3 : Symbol(x3, Decl(strictFunctionTypes1.ts, 14, 5))
>f3 : Symbol(f3, Decl(strictFunctionTypes1.ts, 1, 74))
>fo : Symbol(fo, Decl(strictFunctionTypes1.ts, 6, 58))
>fx : Symbol(fx, Decl(strictFunctionTypes1.ts, 9, 37))

const x4 = f4(fo, fs); // Func<string>
>x4 : Symbol(x4, Decl(strictFunctionTypes1.ts, 15, 5))
>f4 : Symbol(f4, Decl(strictFunctionTypes1.ts, 4, 34))
>fo : Symbol(fo, Decl(strictFunctionTypes1.ts, 6, 58))
>fs : Symbol(fs, Decl(strictFunctionTypes1.ts, 8, 37))

Loading

0 comments on commit 884c72e

Please sign in to comment.