Variables
-
Variable declarations
const x: number = 2 const y: string = 2 const z: object = 4
- Type 2 is not assignable to type string
- Type 4 is not assignable to type object
- Type 'number' is not assignable to type 'string'.
- Type 'number' is not assignable to type 'object'.
-
Variable assignment constraints
let x: number = 3 x = "hello world"
- Type "hello world" is not assignable to type number
- Type 'string' is not assignable to type 'number'.
-
Variable references
const a = 3 const b: string = a
- Type 3 is not assignable to type string
- Type 'number' is not assignable to type 'string'.
-
Variable updates registered
let a = 2 a = "hello world" a satisfies number
- Expected number, found "hello world"
- Type 'string' is not assignable to type 'number'.
-
Variable references does not exist
const exists = 2; nexists
- Could not find variable 'nexists' in scope
- Cannot find name 'nexists'. Did you mean 'exists'?
-
Assigning before declaration
a = 3; let a = 2;
- Cannot assign to 'a' before declaration
- Block-scoped variable 'a' used before its declaration.
-
Assignment to non-existent variable
doesNotExist = 4;
- Cannot assign to unknown variable 'doesNotExist'
- Cannot find name 'doesNotExist'.
-
Variable declared twice
const a = 2 { const a = 3; a satisfies 3; } a satisfies 2; const a = 3;
- Cannot redeclare variable 'a'
- Cannot redeclare block-scoped variable 'a'.
- Cannot redeclare block-scoped variable 'a'.
-
Variable shadowing
const a = 2 { const a = 3; a satisfies 2; }
- Expected 2, found 3
- Type '3' does not satisfy the expected type '2'.
-
Unintialised variables are undefined
let b; b satisfies string;
- Expected string, found undefined
-
TDZ in statements
let first = second; let second = 2;
- Variable 'second' used before declaration
- Block-scoped variable 'second' used before its declaration.
-
var
can be reregistered{ // Fine var x = 2; x satisfies 2; var x = 3; x satisfies 3; } { let b = 2; var b = 2; }
- Cannot redeclare variable 'b'
- Type 'number' does not satisfy the expected type '2'.
- Type 'number' does not satisfy the expected type '3'.
- Cannot initialize outer scoped variable 'b' in the same scope as block scoped declaration 'b'.
Properties
-
Property exists
let my_obj = { a: 3 } const a = my_obj.a const b = my_obj.b
- No property 'b' on { a: 3 }
- Property 'b' does not exist on type '{ a: number; }'.
-
Reading property (via accessor)
const my_obj = { a: 2 } const three: 3 = my_obj.a
- Type 2 is not assignable to type 3
- Type 'number' is not assignable to type '3'.
-
Property updates registered
let my_obj = { a: 3 } my_obj.a = 4 let b: 3 = my_obj.a
- Type 4 is not assignable to type 3
- Type 'number' is not assignable to type '3'.
-
Objects checks
const my_obj: { b: 3 } = { b: 4 }
- Type { b: 4 } is not assignable to type { b: 3 }
- Type '4' is not assignable to type '3'.
-
Getters
let global: number = 0; const object = { // This getter has an impure side effect get value() { return ++global }, } object.value satisfies string object.value satisfies boolean
- Expected string, found 1
- Expected boolean, found 2
- Type 'number' does not satisfy the expected type 'string'.
- Type 'number' does not satisfy the expected type 'boolean'.
-
Getter
this
const object = { x: 4, get value(this: { x: number }) { return this.x }, } object.value satisfies string
- Expected string, found 4
- 'get' and 'set' accessors cannot declare 'this' parameters.
- Type 'number' does not satisfy the expected type 'string'.
-
Setter
this
let a = 2; const obj = { x: 5, set value(this: { x: number }, v) { this.x = v; } } obj.value = "some value"; obj.x satisfies 5;
- Expected 5, found "some value"
- 'get' and 'set' accessors cannot declare 'this' parameters.
- Type 'number' does not satisfy the expected type '5'.
-
Setter assignment type
const obj = { set value(v: string) { } } obj.value = 5;
- Argument of type 5 is not assignable to parameter of type string (in setter)
- Type 'number' is not assignable to type 'string'.
-
Setter side effect
let a = 2; const obj = { x: 5, set value(v) { a = v; } } obj.value = "some value"; a satisfies 2;
- Expected 2, found "some value"
- Type 'number' does not satisfy the expected type '2'.
-
Setter return
const result = ({ set value(a) { return { a: 3 } }}).value = 5; result satisfies string;
- Expected string, found 5
- Setters cannot return a value.
- Type 'number' does not satisfy the expected type 'string'.
-
Object spread
const obj1 = { a: 2, b: 3 }; const obj2 = { b: 4, ...obj1, a: 6 }; obj2.b satisfies 100; obj2.a satisfies boolean;
- Expected 100, found 3
- Expected boolean, found 6
- Type 'number' does not satisfy the expected type '100'.
- Type 'number' does not satisfy the expected type 'boolean'.
-
Set property with key
const obj: { a?: number, b?: number } = { a: 2 } function setProperty(key: "a" | "b", value: number) { obj[key] = value; } setProperty("b", 6) obj satisfies string;
- Expected string, found { a: 2, b: 6 }
- Type '{ a?: number; b?: number; }' does not satisfy the expected type 'string'.
-
Delete properties
const x = { a: 2, b: 3 } delete x.b; const b = x.b;
- No property 'b' on { a: 2 }
-
Object.keys
,Object.values
,Object.entries
Object.keys({ a: 1, b: 2 }) satisfies ["a", "b"]; Object.values({ a: 1, b: 2 }) satisfies [1, 2]; Object.entries({ a: 1, b: 2 }) satisfies boolean;
- Expected boolean, found [["a", 1], ["b", 2]]
- Type 'string[]' does not satisfy the expected type '["a", "b"]'.
- Property 'values' does not exist on type 'ObjectConstructor'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2017' or later.
- Property 'entries' does not exist on type 'ObjectConstructor'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2017' or later.
-
Spread condition
declare let condition: boolean; const obj = { foo: 1, ...(condition ? { bar: 2, non_existent: 3, } : {}), }; obj.foo satisfies number; obj.bar satisfies string;
- Expected string, found 2 | undefined
- Type 'number' does not satisfy the expected type 'string'.
-
And on properties
declare type U = { a: 2 } & { b: 3 } declare let x: U; x.b satisfies 3; ({ a: 2, b: 3 } satisfies U); ({ b: 3 } satisfies U);
- Expected U, found { b: 3 }
- Type '{ b: 3; }' does not satisfy the expected type 'U'.
-
Properties on or
declare let key: "a" | "b"; const object = { a: "apple", b: "banana" }; object[key] satisfies boolean;
- Expected boolean, found "apple" | "banana"
- Type 'string' does not satisfy the expected type 'boolean'.
-
Properties on big or
function func(idx: number) { const array = [1, 2, 3]; array[idx] satisfies string; }
- Expected string, found 1 | 2 | 3 | undefined
- Type 'number' does not satisfy the expected type 'string'.
-
Properties matched against continous type become conditional
declare let strings: { [a: string]: number }; declare let record: Record<string, number>; declare let d: { [a: "a" | "b"]: number }; strings.a satisfies number | undefined; record.a satisfies boolean; d.a satisfies number;
- Expected boolean, found number | undefined
- An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead.
- Type 'number' does not satisfy the expected type 'boolean'.
- Property 'a' does not exist on type '{}'.
-
Un-delete-able property
const x: { a?: number } = { a: 4 }; // Fine delete x.a; const y: { a: number } = { a: 4 }; // Bad delete y.a; const z = {}; Object.defineProperty(z, "a", { value: 4 }); delete z.a;
- Cannot delete from object constrained to { a: number }
- Cannot delete from non-configurable property
- Property 'a' does not exist on type '{}'.
-
Order of numerical properties
let x = {}; x.something = null; x[4] = null; x["eight"] = null; x["2"] = null; x satisfies string;
- Expected string, found { 2: null, 4: null, something: null, eight: null }
- Property 'something' does not exist on type '{}'.
- Type '{}' does not satisfy the expected type 'string'.
-
Order of properties after assignment
const obj = { a: 1, b: 2 }; obj.a = 2; obj.c = 6; obj.b = 4; obj satisfies boolean;
- Expected boolean, found { a: 2, b: 4, c: 6 }
- Property 'c' does not exist on type '{ a: number; b: number; }'.
- Type '{ a: number; b: number; }' does not satisfy the expected type 'boolean'.
-
Assigning to getter
const obj = { get prop() { return 2 } }; obj.prop = "hi"; obj.prop satisfies 2;
- Cannot write to property 'prop' as it is a getter
- Cannot assign to 'prop' because it is a read-only property.
- Type 'number' does not satisfy the expected type '2'.
-
Assinging to non existent property
const obj = { prop: 1 }; // Fine obj.non_existent = 6; function func(param: { prop: number }) { param.notProp = 5; }
- Cannot write to non-existent property 'notProp'
- Property 'non_existent' does not exist on type '{ prop: number; }'.
- Property 'notProp' does not exist on type '{ prop: number; }'.
-
Function and class name
function a() { } class B { } let c = class { } a.name satisfies "a" B.name satisfies "B" c.name satisfies "sea"
- Expected "sea", found "c"
- Property 'name' does not exist on type '() => void'.
- Property 'name' does not exist on type 'typeof B'.
- Property 'name' does not exist on type 'typeof c'.
-
Getters AND setter
let global: number = 0; const object = { get value() { return global }, set value(newValue: number) { global = newValue; } } object.value satisfies string; object.value = 10; object.value satisfies 10; global satisfies 10
- Expected string, found 0
- Type 'number' does not satisfy the expected type 'string'.
- Type 'number' does not satisfy the expected type '10'.
- Type 'number' does not satisfy the expected type '10'.
-
Getters AND setter can be type via
Object.defineProperty
function func(get: () => number) { const obj = {}; Object.defineProperty(obj, "value", { get }); obj.value satisfies string }
- Expected string, found number
- Property 'value' does not exist on type '{}'.
-
enumerable
in for inconst obj = { n: 1, b: 2 }; Object.defineProperty(obj, "c", { value: 3, enumerable: false }); Object.defineProperty(obj, "d", { value: 4, enumerable: true }); let keys: string = ""; for (const key in obj) { keys += key; } keys satisfies boolean
- Expected boolean, found "nbd"
- Type 'string' does not satisfy the expected type 'boolean'.
-
Object.freeze
const obj = {} let result = Object.freeze(obj); (obj === result) satisfies true; obj.property = 2; Object.isFrozen(obj) satisfies true;
- Cannot write to property 'property'
- Type 'boolean' does not satisfy the expected type 'true'.
- Property 'property' does not exist on type '{}'.
- Type 'boolean' does not satisfy the expected type 'true'.
-
Object.defineProperty
writableconst obj = {}; Object.defineProperty(obj, 'property', { value: 42, writable: false, }); obj.property satisfies string; obj.property = 70;
- Expected string, found 42
- Cannot write to property 'property'
- Property 'property' does not exist on type '{}'.
- Property 'property' does not exist on type '{}'.
-
Descriptor carries across assignments
const obj = {}; Object.defineProperty(obj, 'property', { value: 42, enumerable: false, // needed as all properties default to false writable: true, }); obj.property = 70; Object.getOwnPropertyDescriptor(obj, 'property') satisfies string;
- Expected string, found { value: 70, writable: true, enumerable: false, configurable: false }
- Property 'property' does not exist on type '{}'.
- Type 'PropertyDescriptor' does not satisfy the expected type 'string'.
-
Object.defineProperty
getter and setterconst obj = {}; let b = 0; Object.defineProperty(obj, 'property', { get: () => b, }); obj.property satisfies 0; b++; obj.property satisfies string;
- Expected string, found 1
- Property 'property' does not exist on type '{}'.
- Property 'property' does not exist on type '{}'.
-
Object.defineProperty
configurableconst obj = {}; Object.defineProperty(obj, 'property', { value: 6 }); Object.defineProperty(obj, 'property', { value: "hi" });
- Property 'property' not configurable
-
Object.getOwnPropertyDescriptor
const obj = { a: "something" }; Object.defineProperty(obj, 'b', { value: 42 }); Object.getOwnPropertyDescriptor(obj, 'a') satisfies string; Object.getOwnPropertyDescriptor(obj, 'b').writable satisfies false;
- Expected string, found { value: "something", writable: true, enumerable: true, configurable: true }
- Type 'PropertyDescriptor' does not satisfy the expected type 'string'.
- Type 'boolean' does not satisfy the expected type 'false'.
-
Object.assign
const obj = { a: 1 }; Object.assign(obj, { b: 2, c: 3 }); obj satisfies string;
- Expected string, found { a: 1, b: 2, c: 3 } s
- Property 'assign' does not exist on type 'ObjectConstructor'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later.
- Type '{ a: number; }' does not satisfy the expected type 'string'.
Excess properties
-
Excess property at declaration
interface MyObject { property: string } const a: MyObject = { property: "hello", another: 2 }
- 'another' is not a property of MyObject
- Object literal may only specify known properties, and 'another' does not exist in type 'MyObject'.
-
Excess property at argument
interface MyObject { property: string } function process(param: MyObject) {} process({ property: "hello", another: 2 }); function func<T>(a: T) { } func<MyObject>({ property: "hello", "something else": 2 })
- 'another' is not a property of MyObject
- 'something else' is not a property of MyObject
- Object literal may only specify known properties, and 'another' does not exist in type 'MyObject'.
- Object literal may only specify known properties, and '"something else"' does not exist in type 'MyObject'.
-
Excess property at return type
interface MyObject { property: string } function returnNewObject(): MyObject { return { property: "hello", another: 67 } }
- 'another' is not a property of MyObject
- Object literal may only specify known properties, and 'another' does not exist in type 'MyObject'.
-
Excess property checks through spread and condition
type MyObject = { foo: number; bar?: number }; const b: MyObject = { foo: 1, ...{ bar: 2, invalid: 3, }, }; declare let condition: boolean; const c: MyObject = { foo: 1, ...(condition ? { bar: 2, non_existent: 3, } : {}), };
- 'invalid' is not a property of MyObject
- 'non_existent' is not a property of MyObject
Constant evaluation
-
Arithmetic
const x: 4 = 2 + 3 const y: 6 = 2 * 3 const z: 8 = (2 * 3) - 2
- Type 5 is not assignable to type 4
- Type 4 is not assignable to type 8
- Type 'number' is not assignable to type '4'.
- Type 'number' is not assignable to type '6'.
- Type 'number' is not assignable to type '8'.
-
Bitwise arithmetic
const x: 2 = 2 & 3 const y: 6 = 2 ^ 7 const z: 14 = 8 | 4
- Type 5 is not assignable to type 6
- Type 12 is not assignable to type 14
- Type 'number' is not assignable to type '2'.
- Type 'number' is not assignable to type '6'.
- Type 'number' is not assignable to type '14'.
-
Logical operators
const x: 2 = 3 && 2 const y: 6 = 3 && false const z: false = true || 4
- Expression is always true
- Expression is always true
- Type false is not assignable to type 6
- Expression is always true
- Type true is not assignable to type false
- Type '0 | 2' is not assignable to type '2'.
- Type 'false' is not assignable to type '6'.
- Type 'true | 4' is not assignable to type 'false'.
-
Equality
(4 === 2) satisfies true; (4 !== 2) satisfies string;
- Expected true, found false
- Expected string, found true
- This comparison appears to be unintentional because the types '4' and '2' have no overlap.
- Type 'boolean' does not satisfy the expected type 'true'.
- This comparison appears to be unintentional because the types '4' and '2' have no overlap.
- Type 'boolean' does not satisfy the expected type 'string'.
-
Inequality
(Math.PI > 3) satisfies true; (4 < 2) satisfies true; (4 > 2) satisfies number; (6 >= 2) satisfies string; (6 <= 2) satisfies 5;
- Expected true, found false
- Expected number, found true
- Expected string, found true
- Expected 5, found false
- Type 'boolean' does not satisfy the expected type 'true'.
- Type 'boolean' does not satisfy the expected type 'true'.
- Type 'boolean' does not satisfy the expected type 'number'.
- Type 'boolean' does not satisfy the expected type 'string'.
- Type 'boolean' does not satisfy the expected type '5'.
-
String operations (constant functions can use
this
)"hi".toUpperCase() satisfies number
- Expected number, found "HI"
- Type 'string' does not satisfy the expected type 'number'.
-
Math operations
Math.cos(0) satisfies 0 Math.sqrt(16) satisfies 1 Math.floor(723.22) satisfies 2;
- Expected 0, found 1
- Expected 1, found 4
- Expected 2, found 723
- Type 'number' does not satisfy the expected type '0'.
- Type 'number' does not satisfy the expected type '1'.
- Type 'number' does not satisfy the expected type '2'.
-
Updating assignments
let a = 5, b = 6; a++; a satisfies 4; b *= 4; b satisfies 23;
- Expected 4, found 6
- Expected 23, found 24
- Type 'number' does not satisfy the expected type '4'.
- Type 'number' does not satisfy the expected type '23'.
-
Index into string
("something"[2]) satisfies number;
- Expected number, found "m"
- Type 'string' does not satisfy the expected type 'number'.
Function checking
-
Type of parameter
function func(a: number) { a satisfies string }
- Expected string, found number
- Type 'number' does not satisfy the expected type 'string'.
-
Default parameter value type check
function outer(a: number) { function inner(b: string = Math.floor(a)) { } }
- Cannot use a default value of type number for parameter of type string
- Type 'number' is not assignable to type 'string'.
-
(simple) return type checking
function func(): string { return 2 }
- Cannot return 2 because the function is expected to return string
- Type 'number' is not assignable to type 'string'.
-
Type checking basic function types
function func(a: string, b: number): boolean { return true } func satisfies (a: string, b: number) => boolean; func satisfies (a: string, b: number) => string; func satisfies (a: number, b: number) => boolean;
- Expected (a: string, b: number) => string, found (a: string, b: number) => boolean
- Expected (a: number, b: number) => boolean, found (a: string, b: number) => boolean
- Type '(a: string, b: number) => boolean' does not satisfy the expected type '(a: string, b: number) => string'.
- Type '(a: string, b: number) => boolean' does not satisfy the expected type '(a: number, b: number) => boolean'.
-
Return generics mismatch
function getSecond1<T, U>(p1: T, p2: U): U { return p1 } function getSecond2<T, U>(p1: T, p2: U): U { return p2 }
- Cannot return T because the function is expected to return U
- Type 'T' is not assignable to type 'U'.
-
Use of generics in function body
function setFirst1<T, U>(a: T, b: U) { const a2: T = a; } function setFirst2<T, U>(a: T, b: U) { const a2: U = a; }
- Type T is not assignable to type U
- Type 'T' is not assignable to type 'U'.
-
Generics as property
function createObject1<T, U>(a: T, b: U): { a: T, b: U } { return { a, b } } function createObject2<T, U>(a: T, b: U): { a: U, b: U } { return { a, b } }
- Cannot return { a: T, b: U } because the function is expected to return { a: U, b: U }
- Type 'T' is not assignable to type 'U'.
-
Expected parameter from variable declaration
const x: (a: string) => number = a => a.to;
- No property 'to' on string
- Property 'to' does not exist on type 'string'.
-
Expected argument from parameter declaration
function map(a: (a: number) => number) {} // No annotation on `a`. But error comes from body // (rather than parameter assignment) map(a => a.t)
- No property 't' on number
- Property 't' does not exist on type 'number'.
-
Assignment to parameter
function alterParameter(a: number, b: { prop: string }) { a = 2; a = "hi"; b.prop = 3; b.prop = "hello"; // Observed. TODO disabled because of possible impure (getters etc) // b.prop satisfies "hello"; }
- Type "hi" is not assignable to type number
- Type 3 does not meet property constraint string
- Type 'string' is not assignable to type 'number'.
- Type 'number' is not assignable to type 'string'.
-
Variadic function parameter type
function variadic(...r: string[]) { r satisfies boolean; }
- Expected boolean, found Array
- Type 'string[]' does not satisfy the expected type 'boolean'.
- Expected boolean, found Array
-
Destructuring parameter
function myFunction({ a }: { a: number }) { a satisfies boolean; return a } myFunction({ a: 6 }) satisfies string;
- Expected boolean, found number
- Expected string, found 6
- Type 'number' does not satisfy the expected type 'boolean'.
- Type 'number' does not satisfy the expected type 'string'.
-
Return type annotation is used in constraint
function getNumber1(): number { return 4 } function getNumber2() { return 6 } getNumber1 satisfies () => 4; getNumber2 satisfies () => 6; getNumber1() satisfies 4; getNumber2() satisfies 6;
- Expected () => 4, found () => number
- Type '() => number' does not satisfy the expected type '() => 4'.
- Type '() => number' does not satisfy the expected type '() => 6'.
- Type 'number' does not satisfy the expected type '4'.
- Type 'number' does not satisfy the expected type '6'.
-
Function hoisting
function x() { getString(3) } function y() { getString("something") satisfies string; } function getString(param: string): string { return "hi" }
- Argument of type 3 is not assignable to parameter of type string
- Argument of type 'number' is not assignable to parameter of type 'string'.
Inferred return types
-
Simple
function id(a: number) { return a } function simple() { return "hello world" } id satisfies (n: number) => number; simple satisfies () => number;
- Expected () => number, found () => "hello world"
- Type '() => string' does not satisfy the expected type '() => number'.
-
Conditional
function func<T extends boolean>(condition: T) { if (condition) { return 4 } else { return 3 } } func satisfies string;
- Expected string, found
(condition: T) => T ? 4 : 3
- Type '
(condition: T) => 4 | 3' does not satisfy the expected type 'string'.
- Expected string, found
-
Early return
function func(value: number) { if (value === 3) { return "is three" } console.log("hi") return "another" } func satisfies (a: number) => "is three" | "another"; function loop(value: number) { for (let i = 0; i < 10; i++) { if (value === i) { return "something" } } return "another" } loop satisfies (a: number) => "something" | "another"; function sometimes(a: boolean) { if (a) { return "sometimes" } } sometimes satisfies (a: boolean) => string;
- Expected (a: boolean) => string, found (a: boolean) => "sometimes" | undefined
- Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.
-
throw
in bodyfunction throwSomething() { throw "to implement!" } throwSomething satisfies string;
- Expected string, found () => never
- Type '() => void' does not satisfy the expected type 'string'.
Function calling
-
Argument type against parameter
function func(a: number) {} func("hello world")
- Argument of type "hello world" is not assignable to parameter of type number
- Argument of type 'string' is not assignable to parameter of type 'number'.
-
Parameters retain argument values
function id(a) { return a } const d: 3 = id(2)
- Type 2 is not assignable to type 3
-
Get value of property on parameter
function getA(obj: { a: string }) { return obj.a } const d: 3 = getA({ a: "hi" })
- Type "hi" is not assignable to type 3
- Type 'string' is not assignable to type '3'.
-
Missing argument
function func(p1: number, p2: string) {} func(4)
- Missing argument
- Expected 2 arguments, but got 1.
-
Excess argument
function func(p1: number) {} func(4, "extra")
- Excess argument
- Expected 1 arguments, but got 2.
-
Calling non-callable
const x = "hi" x()
- Cannot call type "hi"
- This expression is not callable.
-
Calling higher order function
function addTwoToResult(func: (n: number) => number) { return func(4) + 2 } addTwoToResult((a: number) => a * 4) satisfies 5
- Expected 5, found 18
- Type 'number' does not satisfy the expected type '5'.
-
Calling higher order function that is constant
function call(func: (n: number) => number) { return func(9) } call(Math.sqrt) satisfies 2
- Expected 2, found 3
- Type 'number' does not satisfy the expected type '2'.
-
Constant call and operation with a parameter
function floorPlusB(a: number, b: number) { return Math.floor(a) + b } floorPlusB(100.22, 5) satisfies 8
- Expected 8, found 105
- Type 'number' does not satisfy the expected type '8'.
-
This in object literal
const obj = { a: 4, getA(this: { a: any }) { return this.a } } obj.a = 5; obj.getA() satisfies 6;
- Expected 6, found 5
-
This passed around
function getToUpperCase(s: string) { return s.toUpperCase } getToUpperCase("hi")() satisfies "HEY";
- Expected "HEY", found "HI"
- Type 'string' does not satisfy the expected type '"HEY"'.
-
This as generic argument
function callToUpperCase(s: string) { return s.toUpperCase() } callToUpperCase("hi") satisfies "HEY";
- Expected "HEY", found "HI"
- Type 'string' does not satisfy the expected type '"HEY"'.
-
String internal
this
unbinding errorconst { toUpperCase } = "hi"; toUpperCase();
- The 'this' context of the function is expected to be string, found undefined
-
Calling
new
on a functionfunction MyClass(value) { this.value = value } new MyClass("hi").value satisfies "hello"
- Expected "hello", found "hi"
-
new
on function prototypefunction MyClass(value) { this.value = value } MyClass.prototype.other = 2; const object = new MyClass("hi"); object.value satisfies "hi"; object.other satisfies "hello";
- Expected "hello", found 2
-
Checking with function prototype
function MyClass(this: { other: string }) { } MyClass.prototype.other = 2; const m = new MyClass();
- The 'this' context of the function is expected to be { other: string }, found { other: 2 }
-
Arguments in to rest parameter
function myRestFunction(...r: string[]) { return r } myRestFunction("hello ", "world") satisfies number;
- Expected number, found ["hello ", "world"]
- Type 'string[]' does not satisfy the expected type 'number'.
-
Default parameter
function withDefault(x: number = 1) { return x } withDefault() satisfies 2; withDefault(3) satisfies 3;
- Expected 2, found 1
- Type 'number' does not satisfy the expected type '2'.
- Type 'number' does not satisfy the expected type '3'.
-
Default parameter side effect
let b: number = 0 function doThing(a: number = (b += 2)) { return a } doThing(7); b satisfies 0; doThing(); b satisfies 1;
- Expected 1, found 2
- Type 'number' does not satisfy the expected type '0'.
- Type 'number' does not satisfy the expected type '1'.
-
Optional parameter type
function optionally(p?: number) { p satisfies string; }
- Expected string, found number | undefined
- Type 'number' does not satisfy the expected type 'string'.
-
Calling optional parameter type
function optionally(p?: number) { return p } // Fine optionally() satisfies undefined; optionally(5) satisfies 5; optionally("hello world");
- Argument of type "hello world" is not assignable to parameter of type number | undefined
- Type 'number' does not satisfy the expected type 'undefined'.
- Type 'number' does not satisfy the expected type '5'.
- Argument of type 'string' is not assignable to parameter of type 'number'.
-
Default parameter side effect on parameter
function doThing(a: number, b: number = (a += 2)) { return a } doThing(3) satisfies 2; doThing(6, 1) satisfies 6;
- Expected 2, found 5
- Type 'number' does not satisfy the expected type '2'.
- Type 'number' does not satisfy the expected type '6'.
-
Canceled generics
declare function func<T>(prop: { a: number, b: T, c: string } | { a: number, b: string, c: T }): T; func({ a: 3, b: "hi", c: false }) satisfies string;
- Expected string, found false
- Type 'boolean' is not assignable to type 'string'.
-
Template literal calling error
function myTag(static_parts: Array<string>, count: number) { } myTag`Count is ${"not a number!!"}`;
- Argument of type "not a number!!" is not assignable to parameter of type number (in template literal)
- Argument of type 'TemplateStringsArray' is not assignable to parameter of type 'string[]'.
-
Generics on dependent type
function createNew(cb: { f<T>(t: T): { a: T }}["f"]) { return cb(4) } createNew satisfies string;
- Expected string, found (cb:
(t: T) => { a: T }) => { a: 4 }
- Type '(cb:
(t: T) => { a: T; }) => { a: number; }' does not satisfy the expected type 'string'.
- Expected string, found (cb:
-
Builder pattern
class StringBuilder { s: string = "" append(s: string) { this.s += s; return this } finish() { return this.s } } (new StringBuilder).append("Hello ").append("Ben").finish() satisfies number
- Expected number, found "Hello Ben"
- Type 'string' does not satisfy the expected type 'number'.
-
Dependent operations
function isFive(a: number): boolean { return a === 5 } isFive(5) satisfies true; isFive(6) satisfies string; function hasPropertyX(obj: object): boolean { return "x" in obj; } hasPropertyX({ a: 2 }) satisfies false; hasPropertyX({ x: 5 }) satisfies number;
- Expected string, found false
- Expected number, found true
- Type 'boolean' does not satisfy the expected type 'true'.
- Type 'boolean' does not satisfy the expected type 'string'.
- Type 'boolean' does not satisfy the expected type 'false'.
- Type 'boolean' does not satisfy the expected type 'number'.
Effects
-
Assignment to free variable
let a: number = 0 function func() { a = 4; // Important that subsequent reads use the // new value, not the same free variable a satisfies 4; } func() let b: 2 = a
- Type 4 is not assignable to type 2
- Type 'number' does not satisfy the expected type '4'.
- Type 'number' is not assignable to type '2'.
-
Assignment from parameter
let a: number = 0 function func(c: number) { a = c } func(4) let b: 2 = a
- Type 4 is not assignable to type 2
- Type 'number' is not assignable to type '2'.
-
Free variable property update object inside function
const obj: { a: number } = { a: 2 } function func(value: number) { obj.a = value } obj.a satisfies 2 func(4) obj.a satisfies 3
- Expected 3, found 4
- Type 'number' does not satisfy the expected type '2'.
- Type 'number' does not satisfy the expected type '3'.
-
Effects carry through dependent calls
let a: number = 2 function runFunctionTwice(func: () => void) { func() func() } a satisfies 2 runFunctionTwice(() => { a++ }) a satisfies string
- Expected string, found 4
- Type 'number' does not satisfy the expected type '2'.
- Type 'number' does not satisfy the expected type 'string'.
-
Updates recognised inside of events
let a: number = 2 function runFunctionTwice(func: () => void): number { func() const b = a func() return b; } a satisfies 2 const out = runFunctionTwice(() => { a++ }); a satisfies 4 out satisfies string
- Expected string, found 3
- Type 'number' does not satisfy the expected type '2'.
- Type 'number' does not satisfy the expected type '4'.
- Type 'number' does not satisfy the expected type 'string'.
-
TDZ from free variable (across function)
function getX() { return x } getX satisfies () => number; getX(); let x: number = 5;
- Variable 'x' used before declaration
-
TDZ errors through nested getter
function func(obj: { prop: number }) { return obj.prop } func({ get prop() { return b } }); let b: number = 0;
- Variable 'b' used before declaration
-
Assignment to union
let myObject: { a: number } = { a: 4 } function readA(someObject: { a: number | string }) { return someObject.a; } function setAtoString(someObject: { a: number | string }) { someObject.a = "hi"; } // Allowed readA(myObject); setAtoString({ a: 6 }); setAtoString(myObject);
- Invalid assignment through parameter
-
Property assignment from conditional
function getObject(condition: boolean) { const mainObject = { a: 2 }; const object = condition ? mainObject : { b: 3 }; object.c = 4; mainObject.c satisfies string; return mainObject }
- Expected string, found 4
- Property 'c' does not exist on type '{ a: number; } | { b: number; }'.
- Property 'c' does not exist on type '{ a: number; }'.
-
Assigning to parameter observed via effect
function add_property(obj: { prop: number }) { obj.prop += 2; } const obj = { prop: 4 }; add_property(obj); obj.prop satisfies 8;
- Expected 8, found 6
- Type 'number' does not satisfy the expected type '8'.
-
Functions create objects
function newObject() { return { prop: 2 } } const a = newObject(), b = newObject(); const c = a; (a === c) satisfies false; (a === b) satisfies string;
- Expected false, found true
- Expected string, found false
- Type 'boolean' does not satisfy the expected type 'false'.
- Type 'boolean' does not satisfy the expected type 'string'.
-
Unconditional throw warning
function safeDivide(num: number, denom: number) { if (denom === 0) { throw new Error("Cannot divide by zero"); } return num / denom } function func() { safeDivide(8, 4) satisfies 2; // ahh safeDivide(10, 0); }
- Conditional '[Error] { message: "Cannot divide by zero" }' was thrown in function
- Type 'number' does not satisfy the expected type '2'.
-
Unreachable statement
function throwGreeting() { throw "Hello"; return "Unreachable!" } function doSomething() { throwGreeting() const unreachable = 2; }
- Unreachable statement
- Unreachable statement
-
throw
short-circuitlet x: number = 2; function func(cb: () => void) { try { cb(); x = 10; return "not-thrown" } catch { return "thrown" } } func(() => { throw "error" }) satisfies "thrown"; x satisfies string;
- Expected string, found 2
- Type '"not-thrown" | "thrown"' does not satisfy the expected type '"thrown"'.
- Type 'number' does not satisfy the expected type 'string'.
-
delete
as an effectfunction dewete(param: { prop?: string }) { const { prop } = param; delete param.prop; return prop } const obj = { prop: "hi" }; dewete(obj); obj.prop;
- No property 'prop' on {}
-
Optional effect key
let i: number = 0; ({ a: true})?.[i++, "a"] satisfies true; i satisfies 1; null?.[i++, "a"]; i satisfies string;
- Expression is always false
- Expression is always true
- Expected string, found 1
- Type 'boolean' does not satisfy the expected type 'true'.
- Type 'number' does not satisfy the expected type '1'.
- The value 'null' cannot be used here.
- Type 'number' does not satisfy the expected type 'string'.
-
Effects across functions
let value: number = 2; function a() { value = 8; } function b() { a() } let func = () => {}; function c() { b() } function d(newCb: () => void, then: () => void) { func = newCb; then() } value satisfies 2; d(a, c); value satisfies boolean;
- Expected boolean, found 8
- Type 'number' does not satisfy the expected type '2'.
- Type 'number' does not satisfy the expected type 'boolean'.
Closures
-
Reading variable
function kestrel(a) { return function (_b) { return a } } kestrel(3)(2) satisfies 4
- Expected 4, found 3
-
Nesting
function kestrel2(a) { return _b => _c => a } kestrel2(3)(2)(6) satisfies 4
- Expected 4, found 3
-
Carry across objects
function magicNumber(a: number) { return { plusOne() { return a + 1 }, doubled() { return 2 * a } } } const myNumber = magicNumber(4); // Create a one in between to test they don't have a global state magicNumber(8).doubled() satisfies 16; myNumber.plusOne() satisfies 5 myNumber.doubled() satisfies 6
- Expected 6, found 8
- Type 'number' does not satisfy the expected type '16'.
- Type 'number' does not satisfy the expected type '5'.
- Type 'number' does not satisfy the expected type '6'.
-
Stateful
function myClosure(a) { return { getValue() { return a }, setValue(b) { a = b } } } const value = myClosure(4); value.getValue() satisfies 4; value.setValue(10); value.getValue() satisfies 6
- Expected 6, found 10
-
Class constructors
function func(a: number, b: number) { return class { value: number; constructor() { this.value = a; } plusB() { return this.value + b } } } const c1 = new (func(1, 2)); c1.plusB() satisfies 3; const c2 = new (func(6, 8)); c2.plusB() satisfies string;
- Expected string, found 14
- Type 'number' does not satisfy the expected type '3'.
- Type 'number' does not satisfy the expected type 'string'.
-
Getters closures
function Closure(n: string) { return { get value() { return n }, set value(newValue: string) { n = newValue; } }; } let b = Closure("hi"); b.value = "something"; b.value satisfies number;
- Expected number, found "something"
- Type 'string' does not satisfy the expected type 'number'.
Control flow
-
Resolving conditional
function isNegative(x: number) { return x < 0 ? "negative" : "positive" } isNegative(-4) satisfies number isNegative(4) satisfies boolean
- Expected number, found "negative"
- Expected boolean, found "positive"
- Type 'string' does not satisfy the expected type 'number'.
- Type 'string' does not satisfy the expected type 'boolean'.
-
Conclusive conditional update
let a: number = 0 function conditional(v: string) { if (v === "value") { a++ } } conditional("x") a satisfies 2 conditional("value") a satisfies 3
- Expected 2, found 0
- Expected 3, found 1
- Type 'number' does not satisfy the expected type '2'.
- Type 'number' does not satisfy the expected type '3'.
-
If and else (across function)
function print_number(value: number) { if (value === 0) { return "zero" } else if (value === 1) { return "one" } else { return "some number" } } print_number(0) satisfies "zero" print_number(0) satisfies "some number" print_number(1) satisfies "ONE" print_number(100) satisfies "100" print_number(-1) satisfies "TWO"
- Expected "some number", found "zero"
- Expected "ONE", found "one"
- Expected "100", found "some number"
- Expected "TWO", found "some number"
- Type '"zero" | "one" | "some number"' does not satisfy the expected type '"zero"'.
- Type '"zero" | "one" | "some number"' does not satisfy the expected type '"some number"'.
- Type '"zero" | "one" | "some number"' does not satisfy the expected type '"ONE"'.
- Type '"zero" | "one" | "some number"' does not satisfy the expected type '"100"'.
- Type '"zero" | "one" | "some number"' does not satisfy the expected type '"TWO"'.
-
Operator short circuiting
let a: number = 0 const func = condition => condition || ++a; func(true); a satisfies 0; func(false) satisfies 1; a satisfies 2;
- Expected 2, found 1
- Type 'number' does not satisfy the expected type '0'.
- Type 'number' does not satisfy the expected type '2'.
-
Conditional assignment
let a = false, b = 4; a ||= b++; a satisfies 3; b ||= (b = 10); b satisfies string;
- Expression is always false
- Expected 3, found 4
- Expression is always true
- Expected string, found 5
- Type 'number' is not assignable to type 'boolean'.
- Type 'boolean' does not satisfy the expected type '3'.
- Type 'number' does not satisfy the expected type 'string'.
-
Unknown condition assignment
let i = 0; declare let b: boolean; if (b) { i = 1 } else { i = 2 } i satisfies string;
- Expected string, found 1 | 2
- Type 'number' does not satisfy the expected type 'string'.
-
Conditional return
declare let string: string; function stringIsHi(s: string) { if (s === "hi") { return true } return false } stringIsHi(string) satisfies number;
- Expected number, found boolean
- Type 'boolean' does not satisfy the expected type 'number'.
-
Early return
function func(param: boolean) { let a = 2; if (param) { a = 3; return a; } else { a = 7; } a satisfies string; }
- Expected string, found 7
- Type 'number' does not satisfy the expected type 'string'.
Iteration
-
While loop unrolling
let a: number = 1, i: number = 0; while (i < 5) { a *= 2; i++; } a satisfies 8;
- Expected 8, found 32
- Type 'number' does not satisfy the expected type '8'.
-
While loop event in the condition
let a: number = 1, i: number = 0; while (i++ < 5) { a *= 2; } a satisfies 8;
- Expected 8, found 32
- Type 'number' does not satisfy the expected type '8'.
-
Do while loop
let a: number = 0; do { a++ } while (a < 3) a satisfies 8;
- Expected 8, found 3
- Type 'number' does not satisfy the expected type '8'.
-
For loop with initialiser and condition
let a: string = ""; for (let i: number = 0; i < 10; i++) { a = a + i; } a satisfies number;
- Expected number, found "0123456789"
- Type 'string' does not satisfy the expected type 'number'.
-
While loop with unknown number of iterations
declare let i: number; let a: number = 0; while (a < i) { a++; } a satisfies string;
- Expected string, found number
- Type 'number' does not satisfy the expected type 'string'.
-
Limit to iterations
let a: number = 0; while (a++ < 1_000_000) {} a satisfies string;
- Expected string, found number
- Type 'number' does not satisfy the expected type 'string'.
-
While loop unrolling as a side-effect
function loop(n: number, c: string) { let a: string = c; let i: number = 1; while (i++ < n) { a += c } return a } loop(10, "!") satisfies number;
- Expected number, found "!!!!!!!!!!"
- Type 'string' does not satisfy the expected type 'number'.
-
Break in a while loop
let a: number = 2, i: number = 0; while (i++ < 10) { a *= 2; if (a > 5) { break; } } a satisfies 2;
- Expected 2, found 8
- Type 'number' does not satisfy the expected type '2'.
-
Continue in a while loop
let a: number = 2, i: number = 0; while (i++ < 10) { if (i % 2) { continue; } a *= 2; } a satisfies 2;
- Expected 2, found 64
- Type 'number' does not satisfy the expected type '2'.
-
For-in fixed object
let properties: string = ""; for (const property in { a: 1, b: 2, c: 3 }) { properties += property; } properties satisfies boolean;
- Expected boolean, found "abc"
- Type 'string' does not satisfy the expected type 'boolean'.
-
For-in non fixed object
declare const myObject: { a: 1, b: 2, c: 3 }; let properties: string = ""; for (const property in myObject) { properties += property; } properties satisfies boolean;
- Expected boolean, found string
- Type 'string' does not satisfy the expected type 'boolean'.
Exceptions and `try-catch-finally`
-
Try-catch and throw
try { throw 2 } catch (err) { err satisfies string } console.log("Error caught!")
- Expected string, found 2
- Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.
-
Throw effects carry through
function throwType(a) { throw a } try { throwType(3) } catch (err) { err satisfies string } console.log("Error caught!")
- Expected string, found 3
- Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.
-
Catch annotation
try { throw 3 } catch (err: string) { console.log(err) } console.log("Error caught!")
- Cannot catch type string because the try block throws 3
- Catch clause variable type annotation must be 'any' or 'unknown' if specified.
- Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.
- Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.
-
Function effect
function exceptionToResult(cb: () => number) { try { return cb() } catch (e) { return e } } exceptionToResult(() => 6) satisfies 6; exceptionToResult(() => { throw 12 }) satisfies 8; console.log("Error caught!")
- Expected 8, found 12
- Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.
-
Checked thrown type from callback
function exceptionToResult(cb: () => number) { try { cb() } catch (e: number) { return e } } exceptionToResult(() => { throw "not a number" }); console.log("Error caught!")
- Cannot throw "not a number" in block that expects number
- Catch clause variable type annotation must be 'any' or 'unknown' if specified.
- Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.
-
Internal function effect
function exceptionToResult(s: string) { try { return JSON.parse(s) } catch (e: number) { return e } } console.log("Error caught!")
- Cannot catch type number because the try block throws SyntaxError
- Catch clause variable type annotation must be 'any' or 'unknown' if specified.
- Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.
-
Conditional throw
// no complex numbers :( function checkedLn(x: number) { if (x > 0) { return Math.log(x) } else { throw new Error("Cannot log") } } // Fine try { checkedLn(Math.E ** 3) satisfies 3 } catch {} // Will throw try { checkedLn(-5) } catch {}
- Conditional '[Error] { message: "Cannot log" }' was thrown in function
- Type 'number' does not satisfy the expected type '3'.
-
Throw through internal callback
try { [1, 2, 3].map((x: number) => { if (x === 2) { throw "error" } }); console.log("unreachable") } catch (e) { e satisfies number; }
- Conditional '"error"' was thrown in function
- Unreachable statement
- Expected number, found "error"
- Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.
Collections
-
Array push
const x = [1]; x.push("hi"); x[1] satisfies 3; x.length satisfies 4;
- Expected 3, found "hi"
- Expected 4, found 2
- Argument of type 'string' is not assignable to parameter of type 'number'.
- Type 'number' does not satisfy the expected type '3'.
- Type 'number' does not satisfy the expected type '4'.
-
Array pop
const myArray = [6, "hi"] myArray.pop() satisfies 3; myArray.length satisfies 1;
- Expected 3, found "hi"
- Type 'string | number' does not satisfy the expected type '3'.
- Type 'number' does not satisfy the expected type '1'.
-
Array push restriction
const x: Array<number> = [1] x.push("hi");
- Argument of type "hi" is not assignable to parameter of type number
- Argument of type 'string' is not assignable to parameter of type 'number'.
-
Array map
[6, 8, 10].map(x => x + 1) satisfies [7, 8, 11];
- Expected [7, 8, 11], found [7, 9, 11]
- Type 'number[]' does not satisfy the expected type '[7, 8, 11]'.
-
Mutation
function fakeRead(a: Array<string | number>) { a.push(2) } const array1: Array<string> = [] fakeRead(array1)
- Invalid assignment through parameter
Operators
-
Always known math
// True regardless of function func(a: number) { return a ** 0 } func satisfies string; declare let x: NotNotANumber; (x ** 1 === x) satisfies true;
- Expected string, found (a: number) => 1
- Type '(a: number) => number' does not satisfy the expected type 'string'.
- Cannot find name 'NotNotANumber'.
- Type 'boolean' does not satisfy the expected type 'true'.
-
Inequality checks
function func1(a: GreaterThan<4>) { (a > 3) satisfies true; (a < 3) satisfies false; (a < 10) satisfies string; } // thanks narrowing 🙏 function func2(a: number) { if (a < 2) { (a > 6) satisfies false; (a < 7) satisfies true; (a > 0) satisfies null; } }
- This equality is always false as GreaterThan<4> and 3 have no overlap
- Expected string, found boolean
- This equality is always false as LessThan<2> and 6 have no overlap
- Expected null, found boolean
- Cannot find name 'GreaterThan'.
- Type 'boolean' does not satisfy the expected type 'true'.
- Type 'boolean' does not satisfy the expected type 'false'.
- Type 'boolean' does not satisfy the expected type 'string'.
- Type 'boolean' does not satisfy the expected type 'false'.
- Type 'boolean' does not satisfy the expected type 'true'.
- Type 'boolean' does not satisfy the expected type 'null'.
-
Arithmetic operand check
console + 2
- Cannot Console Add 2
- Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.
-
Inequality operand check
function isLessThan(a: number) { a < console; }
- Cannot number LessThan Console
- Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.
-
Unary operand check
function func(a: number, b: boolean) { const x = !a; const y = ~b; (!b), (~a); }
- Cannot LogicalNot number
- Cannot BitwiseNot boolean
- Left side of comma operator is unused and has no side effects.
-
Disjoint equality
function neverEqual(a: string, b: number) { (a === b) satisfies false; } function sometimes(a: string | number, b: number) { (a === b) satisfies string; }
- This equality is always false as string and number have no overlap
- Expected string, found boolean
- This comparison appears to be unintentional because the types 'string' and 'number' have no overlap.
- Type 'boolean' does not satisfy the expected type 'false'.
- Type 'boolean' does not satisfy the expected type 'string'.
-
Disjoint equality for number intrinsics
declare function getNumberBetweenFive(): InclusiveRange<0, 5> & Integer; getNumberBetweenFive() === 2; getNumberBetweenFive() === 2.2; getNumberBetweenFive() === 7;
- This equality is always false as InclusiveRange<0, 5> & Integer and 2.2 have no overlap
- This equality is always false as InclusiveRange<0, 5> & Integer and 7 have no overlap
- Cannot find name 'InclusiveRange'.
- Cannot find name 'Integer'.
-
Identity equality
function func(a: string, b: number) { (a === a) satisfies string; (b === b) satisfies null; }
- Expected string, found true
- Expected null, found boolean
- Type 'boolean' does not satisfy the expected type 'string'.
- Type 'boolean' does not satisfy the expected type 'null'.
-
Ranges for interal types
function func(a: number) { (Math.sin(a) > -2) satisfies true; (Math.sin(a) > -1) satisfies string; }
- Expected string, found boolean
- Type 'boolean' does not satisfy the expected type 'true'.
- Type 'boolean' does not satisfy the expected type 'string'.
-
Ranges after operators
function func(a: number) { (Math.sin(a) * 5) satisfies null; ((Math.sin(a) + 10)) * 2 satisfies string; }
- Expected null, found InclusiveRange<-5, 5>
- Expected string, found InclusiveRange<18, 22>
- Type 'number' does not satisfy the expected type 'null'.
- Type 'number' does not satisfy the expected type 'string'.
-
Not disjoint
function func(param: number) { if (param !== 2) { return param === 2 } }
- This equality is always false as Not<2> and 2 have no overlap
Statements, declarations and expressions
-
Interfaces
interface X { a: string, b: boolean } const x: X = { a: 2, b: false }
- Type { a: 2, b: false } is not assignable to type X
- Type 'number' is not assignable to type 'string'.
-
Type aliases
type MyNumber = number; type MyObj = { a: string }; "hi" satisfies MyNumber; 4 satisfies MyNumber; declare let obj: MyObj; obj.a satisfies string;
- Expected MyNumber, found "hi"
- Type 'string' does not satisfy the expected type 'number'.
-
Declare variable
declare const global_number: number const my_number: string = global_number
- Type number is not assignable to type string
- Type 'number' is not assignable to type 'string'.
-
Function (and interface) hoisting
getFive() satisfies 4; function getFive() { return 5 } let x: X = { a: 3 } interface X { a: 2 }
- Expected 4, found 5
- Type { a: 3 } is not assignable to type X
- Type 'number' does not satisfy the expected type '4'.
- Type '3' is not assignable to type '2'.
-
Null and undefined
undefined satisfies null; null satisfies undefined;
- Expected null, found undefined
- Expected undefined, found null
-
void operator
(void 2) satisfies string;
- Expected string, found undefined
-
(untagged) Template literal
const name = "Ben"; `Hello ${name}` satisfies "Hi Ben"
- Expected "Hi Ben", found "Hello Ben"
- Type '"Hello Ben"' does not satisfy the expected type '"Hi Ben"'.
-
in
operatorconst obj = { a: 2 }; ("a" in obj) satisfies string; ("b" in obj) satisfies true;
- Expected string, found true
- Expected true, found false
- Type 'boolean' does not satisfy the expected type 'string'.
- Type 'boolean' does not satisfy the expected type 'true'.
-
Type of mathematical operator
declare var x: number; (x * 2) satisfies string
- Expected string, found number
- Type 'number' does not satisfy the expected type 'string'.
-
Type of relation operators
declare var x: number; (x < 4) satisfies string; (x === 4) satisfies Math;
- Expected string, found boolean
- Expected Math, found boolean
- Type 'boolean' does not satisfy the expected type 'string'.
- Type 'boolean' does not satisfy the expected type 'Math'.
-
Type of logical operators
declare var x: number, y: boolean; (x && y) satisfies string;
- Expected string, found boolean | number
- Type 'boolean' does not satisfy the expected type 'string'.
-
Object literal (constant) computed key
const y = { ["EZNO".toLowerCase()]: 7 } y.ezno satisfies 3 y.not_a_key
- Expected 3, found 7
- No property 'not_a_key' on { ezno: 7 }
- Type 'number' does not satisfy the expected type '3'.
-
Shorthand object literal
const x = 2 const y = { x } y.x satisfies 3
- Expected 3, found 2
- Type 'number' does not satisfy the expected type '3'.
-
Object destructuring
const object = { a: 1, b: 2 } const { a, b } = object a satisfies 1; b satisfies string;
- Expected string, found 2
- Type 'number' does not satisfy the expected type '1'.
- Type 'number' does not satisfy the expected type 'string'.
-
Nested object destructuring
const object = { a: { b: { c: 2 } } } const { a: { b: { c: d } } } = object d satisfies 1;
- Expected 1, found 2
- Type 'number' does not satisfy the expected type '1'.
-
Interface merging
interface X { a: string, b: boolean } { interface X { c: number } const x: X = { a: "field", b: false, c: false } const y: X = { a: "field", b: false, c: 2 } }
- Type { a: "field", b: false, c: false } is not assignable to type X
- Type 'boolean' is not assignable to type 'number'.
- Object literal may only specify known properties, and 'a' does not exist in type 'X'.
-
Interfaces do not merge with aliases
type X = { a: string } { interface X { b: number } const x: X = { b: 3 } // Don't require 'a' here <- const y: X = { b: "NaN" } }
- Type { b: "NaN" } is not assignable to type X
- Type 'string' is not assignable to type 'number'.
-
As casts
declare let global: any; 5 as boolean; global satisfies boolean; (global as string) satisfies number;
- Cannot cast 5 to boolean
- Expected boolean, found any
- Expected number, found string
- Conversion of type 'number' to type 'boolean' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
- Type 'string' does not satisfy the expected type 'number'.
-
Non-null assertions
declare const global: { property?: string }; global.property satisfies string | undefined; global.property! satisfies number;
- Expected number, found string
- Type 'string' does not satisfy the expected type 'number'.
-
typeof
operatorfunction func() {} (typeof 5) satisfies "number"; (typeof "hi") satisfies "string"; (typeof func) satisfies "function"; declare let someNumber: number; (typeof someNumber) satisfies "function";
- Expected "function", found "number"
- Type '"string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"' does not satisfy the expected type '"number"'.
- Type '"string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"' does not satisfy the expected type '"string"'.
- Type '"string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"' does not satisfy the expected type '"function"'.
- Type '"string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"' does not satisfy the expected type '"function"'.
-
var
s satisfies string; var s = "hello" s satisfies number;
- Expected string, found undefined
- Expected number, found "hello"
- Type 'string' does not satisfy the expected type 'number'.
-
Object destructuring assignment
const o = { a: 1, b: { c: 3 } }; let a, b, d; ({ d = o.a++, b: { c: b = 7 }, a, } = o); a satisfies string; b satisfies boolean; d satisfies 3;
- Expected string, found 2
- Expected boolean, found 3
- Expected 3, found 1
- Property 'd' does not exist on type '{ a: number; b: { c: number; }; }'.
-
instanceof
operator([] instanceof Array) satisfies true; ({} instanceof Map) satisfies 4; class X {} (new X instanceof X) satisfies true; ([] instanceof X) satisfies false; function isArray(param: any): boolean { return param instanceof Array; } declare let myArray: Array<string>; isArray([1, 2, 3]) satisfies true; isArray(myArray) satisfies string; isArray({ }) satisfies null;
- Expected 4, found false
- Expected string, found true
- Expected null, found false
- Type 'boolean' does not satisfy the expected type 'true'.
- Cannot find name 'Map'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later.
- Type 'boolean' does not satisfy the expected type '4'.
- Type 'boolean' does not satisfy the expected type 'true'.
- Type 'boolean' does not satisfy the expected type 'false'.
- Type 'boolean' does not satisfy the expected type 'true'.
- Type 'boolean' does not satisfy the expected type 'string'.
- Type 'boolean' does not satisfy the expected type 'null'.
-
Tagged template literal
function myTag(static_parts: Array<string>, other: string) { return { static_parts, other } } const name = "Ben"; myTag`${name}Hello ` satisfies string;
- Expected string, found { static_parts: ["", "Hello "], other: "Ben" }
- Argument of type 'TemplateStringsArray' is not assignable to parameter of type 'string[]'.
- Type '{ static_parts: string[]; other: string; }' does not satisfy the expected type 'string'.
-
Interface generic constraint checking
interface BoxString<T extends string> { inner: T } type BoxedFour = BoxString<"4">; type BoxedFive = BoxString<5>;
- Generic argument 5 does not match string
- Type 'number' does not satisfy the constraint 'string'.
-
Mismatch in generic argument count
interface BoxString<T extends string> { inner: T } let x: BoxString<string, number>;
- Expected 1 type argument, but got 2
- Generic type 'BoxString
' requires 1 type argument(s).
-
Optional property access
interface X { a: string b: string } function func(x: X | null) { x.a; x?.b satisfies number; }
- No property 'a' on X | null
- Expected number, found undefined | string
- Type 'string' does not satisfy the expected type 'number'.
Regular expressions
-
RegExp
constructorconst regexp = /hi/ satisfies string;
- Expected string, found /hi/
- Type 'RegExp' does not satisfy the expected type 'string'.
-
Invalid regular expressions
const regexp1 = /(?a2)/; const regexp2 = new RegExp("?a2");
- Invalid regular expression: Invalid token at named capture group identifier
- Invalid regular expression: Invalid atom character
-
Constant
RegExp.exec
const regexp = /hi/; const match = regexp.exec("hi"); match satisfies number; match.index satisfies string; match.input satisfies boolean;
- Expected number, found ["hi"]
- Expected string, found 0
- Expected boolean, found "hi"
- Type 'RegExpExecArray' does not satisfy the expected type 'number'.
- Type 'number' does not satisfy the expected type 'string'.
- Type 'string' does not satisfy the expected type 'boolean'.
-
Constant
RegExp.exec
groupsconst regexp = /Hi (?<name>.*)/; const match = regexp.exec("Hi Ben"); match.input satisfies number; match.groups satisfies string;
- Expected number, found "Hi Ben"
- Expected string, found { name: "Ben" }
- Type 'string' does not satisfy the expected type 'number'.
- Property 'groups' does not exist on type 'RegExpExecArray'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2018' or later.
-
Constant
RegExp.exec
groups greedyconst regexp = /.*(?<x>[a-z]+)(?<y>[0-9]+)/; const match = regexp.exec("ez as abc123"); match.input satisfies number; match.groups.x satisfies "c"; match.groups.y satisfies boolean;
- Expected number, found "ez as abc123"
- Expected boolean, found "123"
- Type 'string' does not satisfy the expected type 'number'.
- Property 'groups' does not exist on type 'RegExpExecArray'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2018' or later.
- Property 'groups' does not exist on type 'RegExpExecArray'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2018' or later.
Async and `Promise`s
-
fetch
const resp = await (fetch("/some-endpoint") satisfies string); resp.ok satisfies number;
- Expected string, found Promise
- Expected number, found boolean
- Cannot find name 'await'. Did you mean to write this in an async function?
- Cannot find name 'fetch'.
- Expected string, found Promise
Classes
-
Constructor
class X { constructor(value) { this.value = value } } const x = new X(4) x.value satisfies string
- Expected string, found 4
- Property 'value' does not exist on type 'X'.
- Property 'value' does not exist on type 'X'.
-
Class
this
unbindingclass X { method() { return this; } } const { method } = new X(); method();
- The 'this' context of the function is expected to be X, found undefined
-
Property keys
let global: number = 0; class X { [global++] = "b"; } global satisfies 0; (new X)[0] satisfies "a"; (new X, new X); global satisfies string;
- Expected 0, found 1
- Expected "a", found "b"
- Expected string, found 1
- A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type.
- Type 'number' does not satisfy the expected type '0'.
- Type 'number' does not satisfy the expected type 'string'.
-
Property field side effects
let global: number = 0; class X { property = ++global; } (new X()).property satisfies string; (new X()).property satisfies 2; (new X()).property satisfies boolean;
- Expected string, found 1
- Expected boolean, found 3
- Type 'number' does not satisfy the expected type 'string'.
- Type 'number' does not satisfy the expected type '2'.
- Type 'number' does not satisfy the expected type 'boolean'.
-
Mix of property fields and assigned
let global: number = 0; class X { prop1 = ++global; constructor() { this.prop2 = ++global; } } const x = new X(); x.prop1 satisfies string; x.prop2 satisfies boolean;
- Expected string, found 1
- Expected boolean, found 2
- Property 'prop2' does not exist on type 'X'. Did you mean 'prop1'?
- Type 'number' does not satisfy the expected type 'string'.
- Property 'prop2' does not exist on type 'X'. Did you mean 'prop1'?
-
Class methods
class X { constructor(value) { this.value = value } getObject(this: { value: any }, b) { return { a: this.value, b } } } const x = new X(4) x.getObject(2) satisfies string
- Expected string, found { a: 4, b: 2 }
- Property 'value' does not exist on type 'X'.
- The 'this' context of type 'X' is not assignable to method's 'this' of type '{ value: any; }'.
- Type '{ a: any; b: any; }' does not satisfy the expected type 'string'.
-
Automatic class constructor
class X { a = 2 } (new X).a satisfies 3
- Expected 3, found 2
- Type 'number' does not satisfy the expected type '3'.
-
Static class property
class X { static a = 2 } X.a satisfies 3
- Expected 3, found 2
- Type 'number' does not satisfy the expected type '3'.
-
Use before defined
const x = new X; class X { }
- Variable 'X' used before declaration
- Class 'X' used before its declaration.
-
Called without new
class X { } const x = X();
- Class constructor must be called with new
- Value of type 'typeof X' is not callable. Did you mean to include 'new'?
-
Class type
extends
class BaseClass { b: boolean = false } class Class extends BaseClass { a: number = 2 } new Class().b satisfies 5
- Expected 5, found false
- Type 'boolean' does not satisfy the expected type '5'.
-
Static blocks
class X { static x = 2; static { const property: 4 = ++this.x; } } X.x satisfies 3;
- Type 3 is not assignable to type 4
- Type 'number' is not assignable to type '4'.
- Type 'number' does not satisfy the expected type '3'.
-
Hoisting of class type
function doThingWithClass(instance: Class) { instance.prop satisfies string; instance.parent_prop satisfies boolean; instance.method(4); } class BaseClass { parent_prop: number } class Class extends BaseClass { prop: number method(s: string) {} }
- Expected string, found number
- Expected boolean, found number
- Argument of type 4 is not assignable to parameter of type string
- Type 'number' does not satisfy the expected type 'string'.
- Type 'number' does not satisfy the expected type 'boolean'.
- Argument of type 'number' is not assignable to parameter of type 'string'.
-
Hoisting of class type with
extends
function doThingWithClass(instance: Class) { instance.a satisfies number; instance.b satisfies string; } class BaseClass { b: boolean } class Class extends BaseClass { a: number }
- Expected string, found boolean
- Type 'boolean' does not satisfy the expected type 'string'.
-
super
calllet b: number = 0; class Y { constructor(a) { this.a = a; b++; } } class X extends Y { constructor(a) { super(a); } } const x = new X("hi"); x.a satisfies "hello"; b satisfies 1;
- Expected "hello", found "hi"
- Property 'a' does not exist on type 'Y'.
- Property 'a' does not exist on type 'X'.
- Type 'number' does not satisfy the expected type '1'.
-
Nominal-ness
class X { a: number = 2 } class Y { a: number = 2} function doThingWithX(x: X) {} doThingWithX(new X()); doThingWithX(new Y())
- Argument of type [Y] { a: 2 } is not assignable to parameter of type X
-
Generics to constructor
class Box<T> { value: T; constructor(value: T) { this.value = value; } } const myBox = new Box<number>("hi");
- Argument of type "hi" is not assignable to parameter of type number
- Argument of type 'string' is not assignable to parameter of type 'number'.
Types
-
Non existent type
type X = number; const a: Y = 2;
- Could not find type 'Y'
- Cannot find name 'Y'.
-
Type shadowing
type X = string; { type X = number; const a: X = "hello world"; }
- Type "hello world" is not assignable to type X
- Type 'string' is not assignable to type 'number'.
-
Type has no generics
type X = number; const a: X<number> = 2;
- Cannot pass a type argument to a non-generic type
- Type 'X' is not generic.
-
Type alias with type parameters
type X<T> = T; 2 satisfies X<string>;
- Expected string, found 2
- Type 'number' does not satisfy the expected type 'string'.
-
Type annotation missing type arguments
type X<T> = T; const b: X = 2;
- Type X requires type arguments
- Generic type 'X' requires 1 type argument(s).
-
Property on an or type
function getProp(obj: { prop: 3, prop2: 6 } | { prop: 2 }) { obj.prop2; return obj.prop } getProp satisfies string
- No property 'prop2' on { prop: 3, prop2: 6 } | { prop: 2 }
- Expected string, found (obj: { prop: 3, prop2: 6 } | { prop: 2 }) => 3 | 2
- Property 'prop2' does not exist on type '{ prop: 3; prop2: 6; } | { prop: 2; }'. Did you mean 'prop'?
- Type '(obj: { prop: 3; prop2: 6; } | { prop: 2; }) => 3 | 2' does not satisfy the expected type 'string'.
-
Generic extends
function getA<T extends { a: string }>(p: T) { return p.a } getA({ a: 2 })
- Argument of type { a: 2 } is not assignable to parameter of type T
- Type 'number' is not assignable to type 'string'.
-
Function parameter subtyping
// Perfectly fine const x: (a: number) => string = (p: string | number) => "hi" // Bad const y: (a: number | string) => string = (p: number) => "hi"
- Type (p: number) => "hi" is not assignable to type (a: number | string) => string
-
Function parameter excess allowed
// Perfectly fine const x: (a: number, b: string) => string = (p: number) => "hi" // Bad const y: (a: string) => string = (p: number, q: string) => "hi"
- Type (p: number, q: string) => "hi" is not assignable to type (a: string) => string
- Type '(p: number, q: string) => string' is not assignable to type '(a: string) => string'.
-
Function return type subtyping
const x: (a: number) => number = p => 4; const y: (a: number) => number = p => "a number"
- Type (p: number) => "a number" is not assignable to type (a: number) => number
- Type 'string' is not assignable to type 'number'.
-
void
return typefunction runWithCallback(cb: () => void): void { cb() satisfies string; return 5; } runWithCallback(() => 3)
- Expected string, found void
- Cannot return 5 because the function is expected to return void
- Type 'void' does not satisfy the expected type 'string'.
- Type 'number' is not assignable to type 'void'.
-
Indexing into (fixed) type
interface ThePrimitives { a: number, b: string, c: boolean } 2 satisfies ThePrimitives["b"];
- Expected string, found 2
- Type 'number' does not satisfy the expected type 'string'.
-
Indexing into (generic) type
function getProp<T extends { prop: string, other: string }>(t: T): T["prop"] { return t.other } function getOther<T extends { prop: string, other: string }>(t: T): T["other"] { return t.other }
- Cannot return T["other"] because the function is expected to return T["prop"]
-
Index into dependent array
function getFirst(array: number[]) { return array[0] } getFirst satisfies boolean;
- Expected boolean, found (array: Array
) => number | undefined
- Type '(array: number[]) => number' does not satisfy the expected type 'boolean'.
- Expected boolean, found (array: Array
-
Index into dependent string
function getSecondCharacter(s: string) { return s[1] } getSecondCharacter satisfies boolean; getSecondCharacter("string") satisfies "b";
- Expected boolean, found (s: string) => string | undefined
- Expected "b", found "t"
- Type '(s: string) => string' does not satisfy the expected type 'boolean'.
- Type 'string' does not satisfy the expected type '"b"'.
-
Symmetric or
function or1<T, U>(obj: T | U): U | T { return obj } function or2(obj: string | number): number | string { return obj } // Lack of symmetry function or3(obj: string | number): number { return obj }
- Cannot return string | number because the function is expected to return number
- Type 'string | number' is not assignable to type 'number'.
-
Symmetric and
function and1<T, U>(obj: T & U): U & T { return obj } // Lack of symmetry function and2<T, U>(obj: T): U & T { return obj }
- Cannot return T because the function is expected to return U & T
- Type 'T' is not assignable to type 'U & T'.
-
Distributivity
function distribute1<T, U, V>(obj: (T | U) & V): (T & V) | (U & V) { return obj } function distribute2<T, U, V>(obj: V & (T | U)): (T & V) | (U & V) { return obj } // bad! function distribute3<T, U, V>(obj: (T | U) & V): (T & U) | (U & V) { return obj }
- Cannot return T & V | U & V because the function is expected to return T & U | U & V
- Type '(T | U) & V' is not assignable to type '(U & V) | (T & U)'.
-
Or object missing property
function get(obj: {a: 2} | { b: 3 }) { return obj.a }
- No property 'a' on { a: 2 } | { b: 3 }
- Property 'a' does not exist on type '{ a: 2; } | { b: 3; }'.
-
Optional interface member
interface Optional { a?: "hi" } const op1: Optional = {} const op2: Optional = { a: "hello" }
- Type { a: "hello" } is not assignable to type Optional
- Type '"hello"' is not assignable to type '"hi"'.
-
Invalid intersection
type X = 2 & "hi"; type Y = string & number;
- No intersection between types 2 and "hi"
- No intersection between types string and number
-
Cyclic type alias
type Node<T> = { parent: Node<T>, value: T } | null; null satisfies Node<number>; ({ parent: { parent: { parent: null, value: 2 }, value: 6 }, value: 2 } satisfies Node<number>); ({ parent: { parent: { parent: null, value: "hi" }, value: 6 }, value: "hi" } satisfies Node<string>);
- Expected { parent: Node
, value: string } | null, found { parent: { parent: { parent: null, value: "hi" }, value: 6 }, value: "hi" }
- Type 'number' is not assignable to type 'string'.
- Expected { parent: Node
-
Cyclic type alias check
type X = Y; type Y = X; // test usage doesn't blow up subtyping const x: X = 2;
- Circular type reference
- Type alias 'X' circularly references itself.
- Type alias 'Y' circularly references itself.
-
Interface extends
interface X { a: string } interface Y { b: string } interface Z extends X, Y { c: string } ({ a: "", b: "", c: "hello" }) satisfies Z; ({ a: "", b: 4, c: "hello" }) satisfies Z; ({ c: "hi" }) satisfies Z;
- Expected Z, found { a: "", b: 4, c: "hello" }
- Expected Z, found { c: "hi" }
- Type 'number' is not assignable to type 'string'.
- Type '{ c: string; }' does not satisfy the expected type 'Z'.
-
never
subtypingfunction getSpecialNumber(): number { throw "to implement!" } getSpecialNumber satisfies string;
- Expected string, found () => number
- Type '() => number' does not satisfy the expected type 'string'.
-
Specialisation of return for declare functions
declare function id<T>(a: T): T; declare function box<T>(a: T): { item: T }; declare let someNumber: number; id(someNumber) satisfies string; box(someNumber) satisfies boolean;
- Expected string, found number
- Expected boolean, found { item: number }
- Type 'number' does not satisfy the expected type 'string'.
- Type '{ item: number; }' does not satisfy the expected type 'boolean'.
-
Template literal type restriction
type Name = "Ben" "test" satisfies `Hello ${Name}`; "Hello Ben" satisfies `Hello ${Name}`;
- Expected string, found "test"
- Type '"test"' does not satisfy the expected type '"Hello Ben"'.
-
Template literal type specialisation
declare function Concat<T extends string, U extends string>(a: T, b: U): `${T}, ${U}`; Concat("test", "something") satisfies boolean
- Expected boolean, found "test, something"
- Type 'string' does not satisfy the expected type 'boolean'.
-
Union with never
declare function func<T>(): T | string; func<number>() satisfies string | number; func<never>() satisfies boolean;
- Expected boolean, found string
- Type 'string' does not satisfy the expected type 'boolean'.
-
Infer and extends distribution
type ElementOf<T> = T extends Array<infer U> ? U : never; declare let elementOfNumber: ElementOf<Array<number>>; declare let elementOfNumberOrString: ElementOf<"not array" | Array<number>>; elementOfNumber satisfies number; elementOfNumberOrString satisfies string; declare let n: never; n satisfies ElementOf<"not array">;
- Expected string, found number
- Type 'number' does not satisfy the expected type 'string'.
-
keyof
type annotationinterface X { a: string, b: string } "a" satisfies keyof X; "b" satisfies keyof X; "c" satisfies keyof X;
- Expected keyof X, found "c"
- Type '"c"' does not satisfy the expected type 'keyof X'.
-
Template literal types
type Introduction = `Hello ${string}`; const first: Introduction = "Hello Ben"; const second: Introduction = "Hi Ben";
- Type "Hi Ben" is not assignable to type Introduction
- Type '"Hi Ben"' is not assignable to type '`Hello ${string}`'.
-
Assigning to types as keys
const obj = { a: 1, b: 2, c: 3 }; obj satisfies { [s: string]: number }; obj satisfies { [s: string]: boolean };
- Expected { [string]: boolean }, found { a: 1, b: 2, c: 3 }
- Type '{ a: number; b: number; c: number; }' does not satisfy the expected type '{ [s: string]: boolean; }'.
-
String slice matching pattern
type GetPrefix<S, End> = S extends `${infer T} ${End}` ? T : false; 4 satisfies GetPrefix<"Hello Ben", "Ben">;
- Expected "Hello", found 4
- Type 'End' is not assignable to type 'string | number | bigint | boolean'.
- Type '4' does not satisfy the expected type '"Hello"'.
-
Infer with extends clause
type X<T> = T extends { a: infer I extends string } ? I : string; declare let a: X<{ a: 4 }>; declare let b: X<{ a: "hello" }>; a satisfies number; b satisfies "hello";
- Expected number, found string
- Type 'string' does not satisfy the expected type 'number'.
-
TSC string intrinsics
const a: Uppercase<"something" |"hi"> = "HI"; const b: Uppercase<string> = "hi"
- Type "hi" is not assignable to type Uppercase
- Type 'string' is not assignable to type 'Uppercase
'.
- Type "hi" is not assignable to type Uppercase
-
NoInfer
declare function func<T>(a: T, b: NoInfer<T>): T; func("hi", "hello") satisfies number;
- Expected number, found "hi"
- Cannot find name 'NoInfer'.
- Type 'string' does not satisfy the expected type 'number'.
-
Subtyping edge cases
"hi" satisfies { length: 3 }; "hi" satisfies { length: 2 }; (() => {}) satisfies Function;
- Expected { length: 3 }, found "hi"
- Type 'string' does not satisfy the expected type '{ length: 3; }'.
- Type 'string' does not satisfy the expected type '{ length: 2; }'.
Generic types
-
Generic interface
interface Wrapper<T> { internal: T } ({ internal: "hi" } satisfies Wrapper<number>); ({ internal: "hi" } satisfies Wrapper<string>);
- Expected Wrapper
, found { internal: "hi" }
- Type 'string' is not assignable to type 'number'.
- Expected Wrapper
-
Array property checking
const numbers1: Array<number> = [1, 2, "3"], numbers2: Array<string> = ["hi", "3"], numbers3: Array<string> = 4;
- Type [1, 2, "3"] is not assignable to type Array
- Type 4 is not assignable to type Array
- Type 'string' is not assignable to type 'number'.
- Type 'number' is not assignable to type 'string[]'.
- Type [1, 2, "3"] is not assignable to type Array
-
Generic type argument parameter
function func<T>(a: T) {} func<number>("hello world")
- Argument of type "hello world" is not assignable to parameter of type number
- Argument of type 'string' is not assignable to parameter of type 'number'.
-
Generics pass down
let c: Array<number> = [] function add() { c.push("hi") }
- Argument of type "hi" is not assignable to parameter of type number
- Argument of type 'string' is not assignable to parameter of type 'number'.
-
Generic condition
declare function isNumber<T>(t: T): T extends number ? "yeess" : "nno"; isNumber(5) satisfies "yeess"; isNumber("5") satisfies number;
- Expected number, found "nno"
- Type 'string' does not satisfy the expected type 'number'.
-
More accurate generic
declare function unwrap<T>(a: T | { item: T }): T; unwrap({ item: 5 }) satisfies string; unwrap(16) satisfies 16;
- Expected string, found 5
- Type 'number' does not satisfy the expected type 'string'.
-
Excess generic arguments
declare function generic<T>(a: T); generic<string, number>("something");
- Expected 1 type argument, but got 2
- Expected 1 type arguments, but got 2.
-
Passing generic type to non-generic function
declare function func(); func<string>();
- Cannot pass a type argument to a non-generic function
- Expected 0 type arguments, but got 1.
-
Across alias
type WithLabel<T> = { label: string, item: T }; declare function getItem<T>(a: WithLabel<T>): T; getItem({ label: "item 1", item: 5 }) satisfies string;
- Expected string, found 5
- Type 'number' does not satisfy the expected type 'string'.
-
Double generics
declare function what<T>(a: T, b: T): T; what(2, 3) satisfies string;
- Expected string, found 2 | 3
- Type 'number' does not satisfy the expected type 'string'.
Mapped types
-
Simple key
type Record2<K extends string, T> = { [P in K]: T } declare let myRecord: Record2<"hi", number>; myRecord.hi satisfies string; myRecord.hello;
- Expected string, found number
- No property 'hello' on { ["hi"]: number }
- Type 'number' does not satisfy the expected type 'string'.
- Property 'hello' does not exist on type 'Record2<"hi", number>'.
-
Assignment
const x: Record<"test", boolean> = { no: false }, y: Record<"test", boolean> = { test: 6 }, z: Record<"test", boolean> = { test: false };
- 'no' is not a property of { ["test"]: boolean }
- Type { no: false } is not assignable to type { ["test"]: boolean }
- Type { test: 6 } is not assignable to type { ["test"]: boolean }
- Object literal may only specify known properties, and 'no' does not exist in type 'Record<"test", boolean>'.
- Type 'number' is not assignable to type 'boolean'.
-
Union and types as keys
declare let obj1: Record<"hi" | "hello", boolean>; obj1.hi satisfies boolean; obj1.hello satisfies boolean; obj1.bye;
- No property 'bye' on { ["hi" | "hello"]: boolean }
- Property 'bye' does not exist on type 'Record<"hi" | "hello", boolean>'.
-
Readonly and optionality carries through
type Mapped<T> = { [P in keyof T]: T[P] } interface Y { readonly a: string, b?: number } declare let x: Mapped<Y>; x.a = "hi"; x.b satisfies number;
- Cannot write to property 'a'
- Expected number, found number | undefined
- Cannot assign to 'a' because it is a read-only property.
-
Specialisation
type Pick<T, K extends keyof T> = { [P in K]: T[P]; }; interface X { a: number, b: string, c: string } ({ a: 5 } satisfies Pick<X, "a">); ({ a: 5 } satisfies Pick<X, "a" | "b">); ({ a: 5, b: "hi" } satisfies Pick<X, "a" | "b">); ({ a: 5, b: 6 } satisfies Pick<X, "a" | "b">); declare let y: Pick<X, "b" | "c">; y.b satisfies string; y.a;
- Expected { ["a" | "b"]: X["a" | "b"] }, found { a: 5 }
- Expected { ["a" | "b"]: X["a" | "b"] }, found { a: 5, b: 6 }
- No property 'a' on { ["b" | "c"]: X["b" | "c"] }
- Duplicate identifier 'Pick'.
- Duplicate identifier 'Pick'.
- Type '{ a: number; }' does not satisfy the expected type 'Pick
'. - Type 'number' is not assignable to type 'string'.
- Property 'a' does not exist on type 'Pick
'.
-
Optional
type Partial<T> = { [P in keyof T]?: T[P]; }; ({ a: 3 } satisfies Partial<{ a: number, b: string }>); ({ a: "hi" } satisfies Partial<{ a: number, b: string }>)
- Expected { [keyof { a: number, b: string }]?: { a: number, b: string }[keyof { a: number, b: string }] }, found { a: "hi" }
- Duplicate identifier 'Partial'.
- Duplicate identifier 'Partial'.
- Type 'string' is not assignable to type 'number'.
-
Negated optionality
type Required<T> = { [P in keyof T]-?: T[P]; }; ({ a: 3 } satisfies Required<{ a?: number }>); // Bad ({ } satisfies Required<{ a?: number }>);
- Expected { [keyof { a?: number }]: { a?: number }[keyof { a?: number }] }, found {}
- Duplicate identifier 'Required'.
- Duplicate identifier 'Required'.
- Type '{}' does not satisfy the expected type 'Required<{ a?: number; }>'.
-
Readonly
type Mutable<T> = { readonly [P in keyof T]: T[P]; }; interface Y { a: string } declare let x: Mutable<Y>; x.a = "hi";
- Cannot write to property 'a'
- Cannot assign to 'a' because it is a read-only property.
-
Negated readonly
type Mutable<T> = { -readonly [P in keyof T]: T[P]; }; interface Y { readonly a: string } declare let x: Mutable<Y>; x.a = "hi"; x.a = 4;
- Type 4 does not meet property constraint "hi"
- Type 'number' is not assignable to type 'string'.
-
as
rewritetype PrefixKeys<T> = { [P in ((keyof T) & string) as `property_${P}`]: T[P]; }; interface X { a: number }; declare let x: PrefixKeys<X>; x.property_a satisfies number; x.property_b
- No property 'property_b' on { [string]: X[keyof X & string] }
- Property 'property_b' does not exist on type 'PrefixKeys
'. Did you mean 'property_a'?
Readonly and `as const`
-
Readonly property
function x(p: { readonly a: string, b: string }) { p.a = "hi"; p.b = "hi"; }
- Cannot write to property 'a'
- Cannot assign to 'a' because it is a read-only property.
-
Readonly to readonly
function func1(p: { a: string, b: string }) { func2(p) } function func2(p: readonly { a: string }) { } const obj = Object.freeze({ a: "hi" }); func2(obj)
- Argument of type { a: string, b: string } is not assignable to parameter of type Readonly<{ a: string }>
- 'readonly' type modifier is only permitted on array and tuple literal types.
Forward inference
-
Object function inference
interface MyObject { a(b: string): any; } const obj: MyObject = { a(b) { b satisfies number; } }
- Expected number, found string
- Type 'string' does not satisfy the expected type 'number'.
-
Generic argument/constraint leads to inference
function callFunction<T>(fn: (p: T) => void) { // ... } callFunction<string>(a => { a satisfies number; })
- Expected number, found string
- Type 'string' does not satisfy the expected type 'number'.
-
Computed generics from collection
const x = [1, 2, 3]; x.map(a => (a satisfies string, 2))
- Expected string, found 1 | 2 | 3
- Type 'number' does not satisfy the expected type 'string'.
Narrowing
-
Equality
function eqNarrow(a: string) { if (a === "hi") { a satisfies "hello" } }
- Expected "hello", found "hi"
- Type '"hi"' does not satisfy the expected type '"hello"'.
-
Condition outside of
if
function eqNarrow(a: string) { const a_equals_hi = a === "hi"; if (a_equals_hi) { a satisfies "hello" } }
- Expected "hello", found "hi"
- Type '"hi"' does not satisfy the expected type '"hello"'.
-
Condition as a function
function eqNarrow(a: string) { function equalsHi(p: string): boolean { return p === "hi" } if (equalsHi(a)) { a satisfies "hello" } }
- Expected "hello", found "hi"
- Type 'string' does not satisfy the expected type '"hello"'.
-
Reference passed around
function eqNarrow(a: string) { const b = a; if (b === "hi") { a satisfies "hello" } }
- Expected "hello", found "hi"
- Type 'string' does not satisfy the expected type '"hello"'.
-
typeof
operatorfunction typeOfNarrow(param: any) { if (typeof param === "string") { param satisfies number; } }
- Expected number, found string
- Type 'string' does not satisfy the expected type 'number'.
-
Boolean narrowing
function booleanNarrow(param: boolean) { if (param) { param satisfies string } if (!param) { param satisfies number } }
- Expected string, found true
- Expected number, found false
- Type 'boolean' does not satisfy the expected type 'string'.
- Type 'boolean' does not satisfy the expected type 'number'.
-
Narrowing from operators
function operatorNarrows(thing: string | null) { (thing ?? "something") satisfies string; (thing || "something") satisfies number; const result = thing === "hi" && (thing satisfies boolean); }
- Expected number, found string | "something"
- Expected boolean, found "hi"
- Type 'string' does not satisfy the expected type 'number'.
- Type 'string' does not satisfy the expected type 'boolean'.
-
Logic
function logicNarrow(thing: any, other: any) { if (typeof thing === "string" && other === 4) { ({ thing, other }) satisfies string; } if (typeof thing === "string" || typeof thing === "number") { thing satisfies null; } }
- Expected string, found { thing: string, other: 4 }
- Expected null, found string | number
- Type '{ thing: string; other: any; }' does not satisfy the expected type 'string'.
- Type 'string | number' does not satisfy the expected type 'null'.
-
Eating cases
function func(param: boolean | string | number) { if (typeof param === "boolean") { return 5 } param satisfies null; }
- Expected null, found string | number
- Type 'string | number' does not satisfy the expected type 'null'.
-
Prototype narrowed
function func(param: Array<string> | string) { if (param instanceof Array) { param satisfies null; } }
- Expected null, found Array
- Type 'string[]' does not satisfy the expected type 'null'.
- Expected null, found Array
-
Type generated from prototype
function func(param: any) { if (param instanceof Array) { param satisfies null; } }
- Expected null, found Array
- Type 'any[]' does not satisfy the expected type 'null'.
- Expected null, found Array
-
Narrowing via property result
function narrowPropertyEquals(param: { tag: "a", a: string } | { tag: "b", b: number }) { if (param.tag === "a") { param.a satisfies string; param satisfies null; } }
- Expected null, found { tag: "a", a: string }
- Type '{ tag: "a"; a: string; }' does not satisfy the expected type 'null'.
-
Narrowing via
in
function narrowFromTag(param: { tag: "a", a: string } | { tag: "b", b: number }) { if ("a" in param) { param.a satisfies string; param satisfies null; } }
- Expected null, found { tag: "a", a: string }
- Type '{ tag: "a"; a: string; }' does not satisfy the expected type 'null'.
-
Build object
function buildObject(param: any) { if ("a" in param) { param satisfies null; } }
- Expected null, found { a: any }
-
Object equality
function conditional(param: boolean) { const obj1 = {}, obj2 = {}; const sum = param ? obj1 : obj2; if (sum === obj1) { sum.a = 2; } [obj1, obj2] satisfies string; }
- Expected string, found [{ a: 2 }, {}]
- Property 'a' does not exist on type '{}'.
- Type '{}[]' does not satisfy the expected type 'string'.
-
From condition equality
function conditional(param: boolean) { const obj1 = { a: 1 }, obj2 = {}; const sum = param ? obj1 : obj2; if (param) { sum satisfies string; } }
- Expected string, found { a: 1 }
- Type '{}' does not satisfy the expected type 'string'.
-
Across free variable
function conditional(param: boolean) { const constant = param; if (constant) { const b = () => constant; b satisfies string; } }
- Expected string, found () => true
- Type '() => true' does not satisfy the expected type 'string'.
-
Edge case
function func1(param: string | number) { if (typeof param === "number" && param > 0) { param satisfies number; } else { param satisfies null; } } function func2(param: string | number | boolean) { if (typeof param === "string" || !(typeof param === "number")) { param satisfies undefined; } else { param satisfies number; } }
- Expected null, found string | number
- Expected undefined, found string | boolean
- Type 'string | number' does not satisfy the expected type 'null'.
- Type 'string | boolean' does not satisfy the expected type 'undefined'.
-
Mutation
function func(param: boolean) { let a = param; const inner = (value: boolean) => a = value; if (a) { inner(false); a satisfies null; } }
- Expected null, found false
- Type 'true' does not satisfy the expected type 'null'.
-
Assertions annotation
function func1(param: any): asserts param is number { if (typeof param !== "string") { throw "bad" } } function func2(param: any): asserts param is boolean { if (typeof param !== "boolean") { throw "bad" } }
- Cannot return asserts any is string because the function is expected to return asserts any is number
-
External predicate
function func(param: number | Array<string>) { if (Array.isArray(param)) { param satisfies null; } }
- Expected null, found Array
- Type 'string[]' does not satisfy the expected type 'null'.
- Expected null, found Array
-
Number
isNan
function func(param: number) { if (param !== param) { param satisfies string; } // Derives from `!==` if (Number.isNaN(param)) { param satisfies null; } }
- Expected string, found Not
- Expected null, found Not
- Type 'number' does not satisfy the expected type 'string'.
- Property 'isNaN' does not exist on type 'NumberConstructor'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later.
- Type 'number' does not satisfy the expected type 'null'.
- Expected string, found Not
-
Narrowing falsy values
function getName(name?: string) { if (name) { name satisfies undefined; return name } else { return "default" } }
- Expected undefined, found string
- Type 'string' does not satisfy the expected type 'undefined'.
Object constraint
-
Object property constraints
const my_obj: { a: number } = { a: 2 } my_obj.a = "hello world"
- Type "hello world" does not meet property constraint number
- Type 'string' is not assignable to type 'number'.
-
Nested constraint
const obj1 = { a: 5 }; const obj2: { prop: { a: number } } = { prop: obj1 } obj1.a = 6; obj1.a = "hello";
- Type "hello" does not meet property constraint number
- Type 'string' is not assignable to type 'number'.
-
And object constraint
{ const obj = { a: true, b: false }; const x: { a: boolean } = obj, y: { b: boolean } = obj; obj.a = "yo"; obj.b = "wassup"; } { // and in the same assignment through a cycle const obj = { a: 2, b: 3 }; obj.c = obj; const something: { a: number, c: { b: number } } = obj; obj.a = "hi"; obj.b = "hello"; }
- Type "yo" does not meet property constraint boolean
- Type "wassup" does not meet property constraint boolean
- Type "hi" does not meet property constraint number
- Type "hello" does not meet property constraint number
- Type 'string' is not assignable to type 'boolean'.
- Type 'string' is not assignable to type 'boolean'.
- Property 'c' does not exist on type '{ a: number; b: number; }'.
- Property 'c' is missing in type '{ a: number; b: number; }' but required in type '{ a: number; c: { b: number; }; }'.
- Type 'string' is not assignable to type 'number'.
- Type 'string' is not assignable to type 'number'.
-
Through another variable
const obj1 = { a: 5 }; const obj2: { prop: { a: number } } = { prop: obj1 } obj1.a = 6; obj1.a = "hello";
- Type "hello" does not meet property constraint number
- Type 'string' is not assignable to type 'number'.
-
Cyclic object check
interface X { a: number b: X } const myObject = { a: 2 }; myObject satisfies X; myObject.b = myObject; myObject satisfies X;
- Expected X, found { a: 2 }
- Type '{ a: number; }' does not satisfy the expected type 'X'.
- Property 'b' does not exist on type '{ a: number; }'.
- Type '{ a: number; }' does not satisfy the expected type 'X'.
Prototypes
-
Set prototype
const x = { a: 3 }; Object.setPrototypeOf(x, { a: 5, b: 2 }); x.a satisfies 3; x.b satisfies string;
- Expected string, found 2
- Property 'setPrototypeOf' does not exist on type 'ObjectConstructor'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later.
- Type 'number' does not satisfy the expected type '3'.
- Property 'b' does not exist on type '{ a: number; }'.
-
Get prototype
const x = { a: 3 }; const p = { b: 2 } Object.setPrototypeOf(x, p); const p_of_x = Object.getPrototypeOf(x); // ('a' in p_of_x.a) satisfies false; (p === p_of_x) satisfies string;
- Expected string, found true
- Property 'setPrototypeOf' does not exist on type 'ObjectConstructor'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later.
- Type 'boolean' does not satisfy the expected type 'string'.
`Proxy`
-
Proxy get
const proxy1 = new Proxy({ a: 2 }, { get(target: { a: number }, prop: string, receiver) { if (prop === "a") { return target["a"] + 1 } } } ); proxy1.a satisfies string;
- Expected string, found 3
- Cannot find name 'Proxy'. Did you mean 'proxy1'?
-
Proxy set
let lastSet: string = ""; const proxy1 = new Proxy({ a: 2 }, { set(target: { a: number }, prop: string, value: number, receiver) { lastSet = prop; } }); proxy1.a = 6; lastSet satisfies boolean;
- Expected boolean, found "a"
- Cannot find name 'Proxy'. Did you mean 'proxy1'?
- Type 'string' does not satisfy the expected type 'boolean'.
-
Proxy handler fallthrough
const obj = { a: 2 }; const proxy1 = new Proxy(obj, { }); proxy1.a = 6; obj.a satisfies 6; proxy1.a satisfies string;
- Expected string, found 6
- Cannot find name 'Proxy'. Did you mean 'proxy1'?
- Type 'number' does not satisfy the expected type '6'.
-
Proxy subtyping
const proxy1 = new Proxy({}, { get(_target, prop, _receiver) { return prop } }); proxy1 satisfies { a: "a", b: "b" }; proxy1 satisfies { c: "d" };
- Expected { c: "d" }, found Proxy [ {}, { get: (_target: any, prop: any, _receiver: any) => any } ]
- Cannot find name 'Proxy'. Did you mean 'proxy1'?
-
Proxy across functions
function makeObservable(obj, cb: (kind: string, prop: string, value: any) => void) { return new Proxy(obj, { get(on, prop: string, _rec) { cb("get", prop, on[prop]) }, set(on, prop: string, _value, _rec) { cb("set", prop, on[prop]) }, }) } let r = null; const value = makeObservable({ a: 1 }, (k, p, v) => { r = { k, p, v }; }); r satisfies null; value.a = 2; r satisfies string;
- Expected string, found { k: "set", p: "a", v: 1 }
- Cannot find name 'Proxy'.
Imports and exports
Stability
-
Use type annotation in the presence of error
const x: string = 5; const y: string = h; function getString(a: number): string { return a } x satisfies string; y satisfies string; const z: number = getString(2);
- Cannot return number because the function is expected to return string
- Type 5 is not assignable to type string
- Could not find variable 'h' in scope
- Type string is not assignable to type number
- Type 'number' is not assignable to type 'string'.
- Cannot find name 'h'.
- Type 'number' is not assignable to type 'string'.
- Type 'string' is not assignable to type 'number'.
-
Errors carries
const obj = { prop: 2 }; console.log(obj.a.b.c); function x() { return y } x().nothing
- Could not find variable 'y' in scope
- No property 'a' on { prop: 2 }
- Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.
- Property 'a' does not exist on type '{ prop: number; }'.
- Cannot find name 'y'.
Extras
-
JSX type
function JSXH(tag_name: string, attributes: any, children: any) { return { tag_name, attributes, children } } const x = <h1 title="Example text">Hello World</h1> satisfies string;
- Expected string, found { tag_name: "h1", attributes: { title: "Example text" }, children: ["Hello World"] }
- Cannot find name 'h1'.
- '>' expected.
- Cannot find name 'title'.
- ',' expected.
- Variable declaration expected.
- Cannot find name 'Hello'.
- ';' expected.
- Cannot find name 'World'.
- Unterminated regular expression literal.
-
Comments as type annotations
function x(a /** string */) { a satisfies number } const c /** number */ = "hello"
- Expected number, found string
- Type "hello" is not assignable to type number
-
Literal special type
function register(a: Literal<string>) { // ... } register("something") // `document.title` is an unknown string, non-literal register(document.title)
- Argument of type string is not assignable to parameter of type Literal
- Cannot find name 'Literal'.
- Cannot find name 'document'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.
- Argument of type string is not assignable to parameter of type Literal
-
Number intrinsics
5 satisfies MultipleOf<2>; 4 satisfies MultipleOf<2>; 6 satisfies GreaterThan<2>; -4 satisfies GreaterThan<2>; 2 satisfies LessThan<2>; -3 satisfies LessThan<2>;
- Expected MultipleOf<2>, found 5
- Expected GreaterThan<2>, found -4
- Expected LessThan<2>, found 2
- Cannot find name 'MultipleOf'.
- Cannot find name 'MultipleOf'.
- Cannot find name 'GreaterThan'.
- Cannot find name 'GreaterThan'.
- Cannot find name 'LessThan'.
- Cannot find name 'LessThan'.
-
Not
declare let a: number; 4 satisfies Not<4>; 6 satisfies Not<4>; a satisfies Not<8>; 2 satisfies Not<string>; "hi" satisfies Not<string>; declare let b: Not<5> & number; b satisfies number; b satisfies string; b satisfies 5;
- Expected Not<4>, found 4
- Expected Not<8>, found number
- Expected Not
, found "hi" - Expected string, found Not<5> & number
- Expected 5, found Not<5> & number
- Cannot find name 'Not'.
- Cannot find name 'Not'.
- Cannot find name 'Not'.
- Cannot find name 'Not'.
- Cannot find name 'Not'.
- Cannot find name 'Not'.
-
Exclusive
interface X { a: number } const x = { a: 1, b: 2 }; x satisfies Exclusive<X>; ({ a: 6 } satisfies Exclusive<X>);
- Expected Exclusive
, found { a: 1, b: 2 }
- Cannot find name 'Exclusive'.
- Cannot find name 'Exclusive'.
- Expected Exclusive
-
CaseInsensitive
"Hi" satisfies CaseInsensitive<"hi">; "Hello" satisfies CaseInsensitive<"hi">; // yeah type CIWord = "WORD" extends Uppercase<infer T> ? T : never; "wOrd" satisfies CIWord; "wood" satisfies CIWord;
- Expected CaseInsensitive<"hi">, found "Hello"
- Expected CIWord, found "wood"
- Cannot find name 'CaseInsensitive'.
- Cannot find name 'CaseInsensitive'.