-
-
Save kaleidawave/81066f322ed574b3373e27770137013f to your computer and use it in GitHub Desktop.
as of 21/09/25 (temp)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| () => { | |
| const x: number = 2 | |
| const y: string = 2 | |
| const z: object = 4 | |
| const a = 3 | |
| const b: string = a | |
| const exists = 2; | |
| nexists | |
| doesNotExist = 4; | |
| let first = second; | |
| let second = 2; | |
| { | |
| // Fine | |
| var x = 2; | |
| x satisfies 2; | |
| var x = 3; | |
| x satisfies 3; | |
| } | |
| { | |
| let b = 2; | |
| var b = 2; | |
| } | |
| const my_obj = { a: 2 } | |
| const three: 3 = my_obj.a | |
| 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 | |
| const obj = { | |
| set value(v: string) { } | |
| } | |
| obj.value = 5; | |
| const result = ({ set value(a) { return { a: 3 } }}).value = 5; | |
| result satisfies string; | |
| const obj1 = { a: 2, b: 3 }; | |
| const obj2 = { b: 4, ...obj1, a: 6 }; | |
| obj2.b satisfies 100; | |
| obj2.a satisfies boolean; | |
| declare type U = { a: 2 } & { b: 3 }; | |
| void function declare_variables(x: U) { | |
| x.b satisfies 3; | |
| ({ a: 2, b: 3 } satisfies U); | |
| ({ b: 3 } satisfies U) | |
| } | |
| function func(idx: number) { | |
| const array = [1, 2, 3]; | |
| array[idx] satisfies string; | |
| } | |
| void function declare_variables(strings: { [a:string]: number }, record: Record<string, number>, d: { [a:"a" | "b"]: number }) { | |
| strings.a satisfies number | undefined; | |
| record.a satisfies boolean; | |
| d.a satisfies number | |
| } | |
| { | |
| const obj = {} | |
| Object.isExtensible(obj) satisfies true; | |
| Object.preventExtensions(obj); | |
| Object.isExtensible(obj) satisfies false; | |
| } | |
| { | |
| const obj = {} | |
| Object.seal(obj); | |
| Object.isExtensible(obj) satisfies false; | |
| } | |
| { | |
| const obj = {} | |
| Object.freeze(obj); | |
| Object.isExtensible(obj) satisfies 5; | |
| } | |
| interface MyObject { property: string } | |
| function returnNewObject(): MyObject { | |
| return { property: "hello", another: 67 } | |
| } | |
| (4 === 2) satisfies true; | |
| (4 !== 5) satisfies string; | |
| (Math.PI > 3) satisfies true; | |
| (4 < 2) satisfies true; | |
| (4 > 2) satisfies number; | |
| (6 >= 2) satisfies string; | |
| (6 <= 2) satisfies 5; | |
| "hi".toUpperCase() satisfies number | |
| Math.cos(0) satisfies 0 | |
| Math.sqrt(16) satisfies 1 | |
| Math.floor(723.22) satisfies 2; | |
| ("something"[2]) satisfies number; | |
| function outer(a: number) { | |
| function inner(b: string = Math.floor(a)) { | |
| } | |
| } | |
| function getSecond1<T, U>(p1: T, p2: U): U { | |
| return p1 | |
| } | |
| function getSecond2<T, U>(p1: T, p2: U): U { | |
| return p2 | |
| } | |
| function setFirst1<T, U>(a: T, b: U) { | |
| const a2: T = a; | |
| } | |
| function setFirst2<T, U>(a: T, b: U) { | |
| const a2: U = a; | |
| } | |
| 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 } | |
| } | |
| function map(a: (a: number) => number) {} | |
| // No annotation on `a`. But error comes from body | |
| // (rather than parameter assignment) | |
| map(a => a.t); | |
| 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"; | |
| } | |
| function variadic(...r: string[]) { | |
| r satisfies boolean; | |
| } | |
| function myFunction({ a }: { a: number }) { | |
| a satisfies boolean; | |
| return a | |
| } | |
| myFunction({ a: 6 }) satisfies string; | |
| function getNumber1(): number { | |
| return 4 | |
| } | |
| function getNumber2() { | |
| return 6 | |
| } | |
| getNumber1 satisfies () => 4; | |
| getNumber2 satisfies () => 6; | |
| getNumber1() satisfies 4; | |
| getNumber2() satisfies 6; | |
| function id(a: number) { | |
| return a | |
| } | |
| function simple() { | |
| return "hello world" | |
| } | |
| id satisfies (n: number) => number; | |
| simple satisfies () => number; | |
| function throwSomething() { | |
| throw "to implement!" | |
| } | |
| throwSomething satisfies string; | |
| function getA(obj: { a: string }) { | |
| return obj.a | |
| } | |
| const d: 3 = getA({ a: "hi" }); | |
| function addTwoToResult(func: (n: number) => number) { | |
| return func(4) + 2 | |
| } | |
| addTwoToResult((a: number) => a * 4) satisfies 5 | |
| function call(func: (n: number) => number) { | |
| return func(9) | |
| } | |
| call(Math.sqrt) satisfies 2 | |
| function floorPlusB(a: number, b: number) { | |
| return Math.floor(a) + b | |
| } | |
| floorPlusB(100.22, 5) satisfies 8 | |
| function getToUpperCase(s: string) { | |
| return s.toUpperCase | |
| } | |
| getToUpperCase("hi")() satisfies "HEY"; | |
| function callToUpperCase(s: string) { | |
| return s.toUpperCase() | |
| } | |
| callToUpperCase("hi") satisfies "HEY"; | |
| const { toUpperCase } = "hi"; | |
| toUpperCase(); | |
| function MyClass(value) { | |
| this.value = value | |
| } | |
| new MyClass("hi").value satisfies "hello" | |
| function myRestFunction(...r: string[]) { | |
| return r | |
| } | |
| myRestFunction("hello ", "world") satisfies number; | |
| function withDefault(x: number = 1) { | |
| return x | |
| } | |
| withDefault() satisfies 2; | |
| withDefault(3) satisfies 3; | |
| function optionally(p?: number) { | |
| p satisfies string; | |
| } | |
| function doThing(a: number, b: number = (a += 2)) { | |
| return a | |
| } | |
| doThing(3) satisfies 2; | |
| doThing(6, 1) satisfies 6; | |
| function myTag(static_parts: Array<string>, count: number) { | |
| } | |
| myTag`Count is ${"not a number!!"}`; | |
| function createNew(cb: { f<T>(t: T): { a: T }}["f"]) { | |
| return cb(4) | |
| } | |
| createNew satisfies string; | |
| 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 | |
| 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; | |
| 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); | |
| function getObject(condition: boolean) { | |
| const mainObject = { a: 2 }; | |
| const object = condition ? mainObject : { b: 3 }; | |
| object.c = 4; | |
| mainObject.c satisfies string; | |
| return mainObject | |
| } | |
| function throwGreeting() { | |
| throw "Hello"; | |
| return "Unreachable!" | |
| } | |
| function doSomething() { | |
| throwGreeting() | |
| const unreachable = 2; | |
| } | |
| let i: number = 0; | |
| ({ a: true})?.[i++, "a"] satisfies true; | |
| i satisfies 1; | |
| null?.[i++, "a"]; | |
| i satisfies string; | |
| function kestrel(a) { | |
| return function (_b) { | |
| return a | |
| } | |
| } | |
| kestrel(3)(2) satisfies 4 | |
| function kestrel2(a) { | |
| return b => c => (a * b) + c | |
| } | |
| kestrel2(3)(2)(1) satisfies 4 | |
| 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 | |
| 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 | |
| function isNegative(x: number) { | |
| return x < 0 ? "negative" : "positive" | |
| } | |
| isNegative(-4) satisfies number | |
| isNegative(4) satisfies boolean | |
| 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" | |
| void function declare_variables(string: string) { | |
| function stringIsHi(s: string) { | |
| if (s === "hi") { | |
| return true | |
| } | |
| return false | |
| } | |
| stringIsHi(string) satisfies number | |
| } | |
| 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; | |
| let properties: string = ""; | |
| for (const property in { a: 1, b: 2, c: 3 }) { | |
| properties += property; | |
| } | |
| properties satisfies boolean; | |
| try { | |
| throw 2 | |
| } catch (err) { | |
| err satisfies string | |
| } | |
| console.log("Error caught!"); | |
| function exceptionToResult(cb: () => number) { | |
| try { | |
| return cb() | |
| } catch (e) { | |
| return e | |
| } | |
| } | |
| exceptionToResult(() => 6) satisfies 6; | |
| exceptionToResult(() => { throw 12 }) satisfies 8; | |
| console.log("Error caught!"); | |
| // 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 {} | |
| const myArray = [6, "hi"] | |
| myArray.pop() satisfies 3; | |
| myArray.length satisfies 1; | |
| function fakeRead(a: Array<string | number>) { | |
| a.push(2) | |
| } | |
| const array1: Array<string> = [] | |
| fakeRead(array1); | |
| console + 2 | |
| function isLessThan(a: number) { | |
| a < console; | |
| } | |
| function neverEqual(a: string, b: number) { | |
| (a === b) satisfies false; | |
| } | |
| function sometimes(a: string | number, b: number) { | |
| (a === b) satisfies string; | |
| } | |
| void function declare_variables(getNumberBetweenFive: () => InclusiveRange<0, 5> & Integer) { | |
| getNumberBetweenFive() === 2; | |
| getNumberBetweenFive() === 2.2; | |
| getNumberBetweenFive() === 7 | |
| } | |
| function func1(param: Not<string>) { | |
| return "hi" === param; | |
| } | |
| function func2(param: Not<string>) { | |
| return 4 === param; | |
| } | |
| function func3(p1: Not<string>, p2: Not<number>) { | |
| return p1 === p2; | |
| } | |
| type MyNumber = number; | |
| type MyObj = { a: string }; | |
| void function declare_variables(obj: MyObj) { | |
| "hi" satisfies MyNumber; | |
| 4 satisfies MyNumber; | |
| obj.a satisfies string | |
| } | |
| void function declare_variables(global_number: number) { | |
| const my_number: string = global_number | |
| } | |
| undefined satisfies null; | |
| null satisfies undefined; | |
| (void 2) satisfies string; | |
| const name = "Ben"; | |
| `Hello ${name}` satisfies "Hi Ben" | |
| void function declare_variables(x: number) { | |
| (x * 2) satisfies string | |
| } | |
| void function declare_variables(x: number) { | |
| (x < 4) satisfies string; | |
| (x === 4) satisfies Math; | |
| (x !== 4) satisfies boolean; | |
| (x > 4) satisfies boolean; | |
| (x >= 4) satisfies boolean | |
| } | |
| void function declare_variables(x: number, y: boolean) { | |
| (x && y) satisfies string | |
| } | |
| 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 } | |
| } | |
| void function declare_variables(global: any) { | |
| 5 as boolean; | |
| global satisfies boolean; | |
| (global as string) satisfies number | |
| } | |
| void function declare_variables(global: { property: string }) { | |
| global.property satisfies string | undefined; | |
| global.property! satisfies number | |
| } | |
| s satisfies string; | |
| var s = "hello" | |
| s satisfies number; | |
| interface BoxString<T extends string> { | |
| inner: T | |
| } | |
| type BoxedFour = BoxString<"4">; | |
| type BoxedFive = BoxString<5>; | |
| const regexp = /hi/ satisfies string; | |
| const regexp1 = /(?a2)/; | |
| const regexp2 = new RegExp("?a2"); | |
| const resp = await (fetch("/some-endpoint") satisfies string); | |
| resp.ok satisfies number; | |
| class BaseClass { | |
| b: boolean = false | |
| } | |
| class Class extends BaseClass { | |
| a: number = 2 | |
| } | |
| new Class().b satisfies 5 | |
| class Box<T> { | |
| value: T; | |
| constructor(value: T) { | |
| this.value = value; | |
| } | |
| } | |
| const myBox = new Box<number>("hi"); | |
| function getProp(obj: { prop: 3, prop2: 6 } | { prop: 2 }) { | |
| obj.prop2; | |
| return obj.prop | |
| } | |
| getProp satisfies string | |
| function runWithCallback(cb: () => void): void { | |
| cb() satisfies string; | |
| return 5; | |
| } | |
| runWithCallback(() => 3); | |
| interface ThePrimitives { | |
| a: number, | |
| b: string, | |
| c: boolean | |
| } | |
| 2 satisfies ThePrimitives["b"]; | |
| function getFirst(array: number[]) { | |
| return array[0] | |
| } | |
| getFirst satisfies boolean; | |
| function getSecondCharacter(s: string) { | |
| return s[1] | |
| } | |
| getSecondCharacter satisfies boolean; | |
| getSecondCharacter("string") satisfies "b"; | |
| 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 } | |
| function and1<T, U>(obj: T & U): U & T { return obj } | |
| // Lack of symmetry | |
| function and2<T, U>(obj: T): U & T { return obj } | |
| 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 } | |
| function get(obj: {a: 2} | { b: 3 }) { | |
| return obj.a | |
| } | |
| interface Optional { | |
| a?: "hi" | |
| } | |
| const op1: Optional = {} | |
| const op2: Optional = { a: "hello" } | |
| 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>); | |
| function getSpecialNumber(): number { | |
| throw "to implement!" | |
| } | |
| getSpecialNumber satisfies string; | |
| void function declare_variables(Concat: <T extends string, U extends string>(a: T, b: U) => `${T}, ${U}`) { | |
| Concat("test", "something") satisfies boolean | |
| } | |
| type ElementOf<T> = T extends Array<infer U> ? U : never; | |
| void function declare_variables(elementOfNumber: ElementOf<Array<number>>, elementOfNumberOrString: ElementOf<"not array" | Array<number>>, n: never) { | |
| elementOfNumber satisfies number; | |
| elementOfNumberOrString satisfies string; | |
| n satisfies ElementOf<"not array"> | |
| } | |
| type GetPrefix<S, End> = S extends `${infer T} ${End}` ? T : false; | |
| 4 satisfies GetPrefix<"Hello Ben", "Ben">; | |
| "hi" satisfies { length: 3 }; | |
| "hi" satisfies { length: 2 }; | |
| (() => {}) satisfies Function; | |
| interface Wrapper<T> { | |
| internal: T | |
| } | |
| ({ internal: "hi" } satisfies Wrapper<number>); | |
| ({ internal: "hi" } satisfies Wrapper<string>); | |
| const numbers1: Array<number> = [1, 2, "3"], | |
| numbers2: Array<string> = ["hi", "3"], | |
| numbers3: Array<string> = 4; | |
| let c: Array<number> = [] | |
| function add() { | |
| c.push("hi") | |
| } | |
| void function declare_variables(isNumber: <T>(t: T) => T extends number ? "yeess" : "nno") { | |
| isNumber(5) satisfies "yeess"; | |
| isNumber("5") satisfies number | |
| } | |
| void function declare_variables(unwrap: <T>(a: T | { item: T }) => T) { | |
| unwrap({ item: 5 }) satisfies string; | |
| unwrap(16) satisfies 16 | |
| } | |
| void function declare_variables(generic: <T>(a: T) => any) { | |
| generic<string, number>("something") | |
| } | |
| type WithLabel<T> = { label: string, item: T }; | |
| void function declare_variables(getItem: <T>(a: WithLabel<T>) => T) { | |
| getItem({ label: "item 1", item: 5 }) satisfies string | |
| } | |
| void function declare_variables(what: <T>(a: T, b: T) => T) { | |
| what(2, 3) satisfies string | |
| } | |
| type Record2<K extends string, T> = { [P in K]: T }; | |
| void function declare_variables(myRecord: Record2<"hi", number>) { | |
| myRecord.hi satisfies string; | |
| myRecord.hello | |
| } | |
| void function declare_variables(obj1: Record<"hi" | "hello", boolean>) { | |
| obj1.hi satisfies boolean; | |
| obj1.hello satisfies boolean; | |
| obj1.bye | |
| } | |
| type Mapped<T> = { [P in keyof T]: T[P] }; | |
| interface Y { | |
| readonly a: string | |
| b: number | |
| } | |
| void function declare_variables(x: Mapped<Y>) { | |
| x.a = "hi"; | |
| x.b satisfies number | |
| } | |
| 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 }>); | |
| type Required<T> = { | |
| [P in keyof T]-?: T[P]; | |
| }; | |
| ({ a: 3 } satisfies Required<{ a?: number }>); | |
| // Bad | |
| ({ } satisfies Required<{ a?: number }>); | |
| function callFunction<T>(fn: (p: T) => void) { | |
| // ... | |
| } | |
| callFunction<string>(a => { | |
| a satisfies number; | |
| }); | |
| function eqNarrow(a: string) { | |
| if (a === "hi") { | |
| a satisfies "hello" | |
| } | |
| } | |
| function typeOfNarrow(param: any) { | |
| if (typeof param === "string") { | |
| param satisfies number; | |
| } | |
| } | |
| function booleanNarrow(param: boolean) { | |
| if (param) { | |
| param satisfies string | |
| } | |
| if (!param) { | |
| param satisfies number | |
| } | |
| } | |
| function operatorNarrows(thing: string | null) { | |
| (thing ?? "something") satisfies string; | |
| (thing || "something") satisfies number; | |
| const result = thing === "hi" && (thing satisfies boolean); | |
| } | |
| 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; | |
| } | |
| } | |
| function narrowPropertyEquals(param: { tag: "a", a: string } | { tag: "b", b: number }) { | |
| if (param.tag === "a") { | |
| param.a satisfies string; | |
| param satisfies null; | |
| } | |
| } | |
| function narrowFromTag(param: { tag: "a", a: string } | { tag: "b", b: number }) { | |
| if ("a" in param) { | |
| param.a satisfies string; | |
| param satisfies null; | |
| } | |
| } | |
| function buildObject(param: any) { | |
| if ("a" in param) { | |
| param satisfies null; | |
| } | |
| } | |
| function conditional(param: boolean) { | |
| const obj1 = { b: 2 }, obj2 = { c: 6 }; | |
| const sum = param ? obj1 : obj2; | |
| if (sum === obj1) { | |
| sum.a = 3; | |
| } | |
| [obj1, obj2] satisfies string; | |
| } | |
| function getName(name?: string) { | |
| if (name) { | |
| name satisfies undefined; | |
| return name | |
| } else { | |
| return "default" | |
| } | |
| } | |
| { | |
| 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"; | |
| } | |
| const proxy1 = new Proxy({ a: 2 }, { get(target: { a: number }, prop: string, receiver) { | |
| if (prop === "a") { | |
| return target["a"] + 1 | |
| } | |
| } } ); | |
| proxy1.a satisfies string; | |
| 5 satisfies MultipleOf<2>; | |
| 4 satisfies MultipleOf<2>; | |
| 6 satisfies GreaterThan<2>; | |
| -4 satisfies GreaterThan<2>; | |
| 2 satisfies LessThan<2>; | |
| -3 satisfies LessThan<2>; | |
| void function declare_variables(a: number, b: Not<5> & number) { | |
| 4 satisfies Not<4>; | |
| 6 satisfies Not<4>; | |
| a satisfies Not<8>; | |
| 2 satisfies Not<string>; | |
| "hi" satisfies Not<string>; | |
| b satisfies number; | |
| b satisfies string; | |
| b satisfies 5 | |
| } | |
| "Hi" satisfies CaseInsensitive<"hi">; | |
| "Hello" satisfies CaseInsensitive<"hi">; | |
| // yeah | |
| type CIWord = "WORD" extends Uppercase<infer T> ? T : never; | |
| "wOrd" satisfies CIWord; | |
| "wood" satisfies CIWord; | |
| }; | |
| () => { | |
| let x: number = 3 | |
| x = "hello world" | |
| let a = 2 | |
| a = "hello world" | |
| a satisfies number | |
| let b; | |
| b satisfies string; | |
| const my_obj: { b: 3 } = { b: 4 } | |
| const object = { | |
| x: 4, | |
| get value(this: { x: number }) { | |
| return this.x | |
| }, | |
| } | |
| object.value satisfies string | |
| const obj: { a?: number, b?: number } = { a: 2 } | |
| function setProperty(key: "a" | "b", value: number) { | |
| obj[key] = value; | |
| } | |
| setProperty("b", 6) | |
| obj satisfies string; | |
| function func(get: () => number) { | |
| const obj = {}; | |
| Object.defineProperty(obj, "value", { get }); | |
| obj.value satisfies string | |
| } | |
| function id(a) { | |
| return a | |
| } | |
| const d: 3 = id(2); | |
| function MyClass(this: { other: string }) { } | |
| MyClass.prototype.other = 2; | |
| const m = new MyClass(); | |
| function optionally(p?: number) { | |
| return p | |
| } | |
| // Fine | |
| optionally() satisfies undefined; | |
| optionally(5) satisfies 5; | |
| optionally("hello world"); | |
| void function declare_variables(b: boolean) { | |
| let i = 0; | |
| if (b) { | |
| i = 1 | |
| } else { | |
| i = 2 | |
| } | |
| i satisfies string | |
| } | |
| void function declare_variables(myObject: { a: 1, b: 2, c: 3 }) { | |
| let properties: string = ""; | |
| for (const property in myObject) { | |
| properties += property | |
| } | |
| properties satisfies boolean | |
| } | |
| function throwType(a) { | |
| throw a | |
| } | |
| try { | |
| throwType(3) | |
| } catch (err) { | |
| err satisfies string | |
| } | |
| console.log("Error caught!"); | |
| function exceptionToResult(cb: () => number) { | |
| try { | |
| cb() | |
| } catch (e: number) { | |
| return e | |
| } | |
| } | |
| exceptionToResult(() => { throw "not a number" }); | |
| console.log("Error caught!"); | |
| const value: string = 0 / 0 + 1; | |
| const y = { ["EZNO".toLowerCase()]: 7 } | |
| y.ezno satisfies 3 | |
| y.not_a_key | |
| type X = { a: string } | |
| { | |
| interface X { | |
| b: number | |
| } | |
| const x: X = { b: 3 } // Don't require 'a' here <- | |
| const y: X = { b: "NaN" } | |
| } | |
| function myTag(static_parts: Array<string>, other: string) { | |
| return { static_parts, other } | |
| } | |
| const name = "Ben"; | |
| myTag`${name}Hello ` satisfies string; | |
| const regexp = /hi/; | |
| const match = regexp.exec("hi"); | |
| match satisfies number; | |
| match.index satisfies string; | |
| match.input satisfies boolean; | |
| 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) {} | |
| } | |
| function getA<T extends { a: string }>(p: T) { | |
| return p.a | |
| } | |
| getA({ a: 2 }); | |
| 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 | |
| } | |
| type Introduction = `Hello ${string}`; | |
| const first: Introduction = "Hello Ben"; | |
| const second: Introduction = "Hi Ben"; | |
| const third: `Hiya ${string}` = "Hello Ben"; | |
| // Edge cases | |
| const invalidNum1: `${1}` = 1; | |
| const invalidNum2: `${1}` = "1"; | |
| const invalidNum3: `${1}` = "2"; | |
| type Immutable<T> = { readonly [P in keyof T]: T[P] }; | |
| interface Y { | |
| a: string | |
| } | |
| void function declare_variables(x: Immutable<Y>) { | |
| x.a = "hi" | |
| } | |
| function eqNarrow(a: string) { | |
| const a_equals_hi = a === "hi"; | |
| if (a_equals_hi) { | |
| a satisfies "hello" | |
| } | |
| } | |
| function conditional(param: boolean) { | |
| const obj1 = { a: 1 }, obj2 = { b: 2}; | |
| const sum = param ? obj1 : obj2; | |
| if (param) { | |
| sum satisfies string; | |
| } | |
| } | |
| 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; | |
| } | |
| } | |
| void function declare_variables(isNumber: (param: any) => asserts param is number, value: any) { | |
| if (isNumber(value)) { | |
| value satisfies string | |
| } | |
| } | |
| const obj1 = { a: 5 }; | |
| const obj2: { prop: { a: number } } = { prop: obj1 } | |
| obj1.a = 6; | |
| obj1.a = "hello"; | |
| 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; | |
| }; | |
| () => { | |
| a = 3; | |
| let a = 2; | |
| let my_obj = { a: 3 } | |
| my_obj.a = 4 | |
| let b: 3 = my_obj.a | |
| void function declare_variables(condition: boolean) { | |
| const obj = { foo: 1, ...(condition ? { bar: 2, non_existent: 3 } : { }) }; | |
| obj.foo satisfies number; | |
| obj.bar satisfies string | |
| } | |
| void function declare_variables(key: "a" | "b") { | |
| const object = { a: "apple", b: "banana" }; | |
| object[key] satisfies boolean | |
| } | |
| 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; | |
| 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 }); | |
| try { | |
| throw 3 | |
| } catch (err: string) { | |
| console.log(err) | |
| } | |
| console.log("Error caught!"); | |
| function exceptionToResult(s: string) { | |
| try { | |
| return JSON.parse(s) | |
| } catch (e: number) { | |
| return e | |
| } | |
| } | |
| console.log("Error caught!"); | |
| void function declare_variables(myArray: Array<string>) { | |
| ([] 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 | |
| } | |
| isArray([1, 2, 3]) satisfies true; | |
| isArray(myArray) satisfies string; | |
| isArray({ }) satisfies null | |
| } | |
| const regexp = /Hi (?<name>.*)/; | |
| const match = regexp.exec("Hi Ben"); | |
| match.input satisfies number; | |
| match.groups satisfies string; | |
| function doThingWithClass(instance: Class) { | |
| instance.a satisfies number; | |
| instance.b satisfies string; | |
| } | |
| class BaseClass { | |
| b: boolean | |
| } | |
| class Class extends BaseClass { | |
| a: number | |
| } | |
| void function declare_variables(id: <T>(a: T) => T, box: <T>(a: T) => { item: T }, someNumber: number) { | |
| id(someNumber) satisfies string; | |
| box(someNumber) satisfies boolean | |
| } | |
| type Mutable<T> = { -readonly [P in keyof T]: T[P] }; | |
| interface Y { | |
| readonly a: string | |
| } | |
| void function declare_variables(x: Mutable<Y>) { | |
| x.a = 4; | |
| x.a = "hi" | |
| } | |
| function eqNarrow(a: string) { | |
| function equalsHi(p: string): boolean { return p === "hi" } | |
| if (equalsHi(a)) { | |
| a satisfies "hello" | |
| } | |
| } | |
| function conditional(param: boolean) { | |
| const constant = param; | |
| if (constant) { | |
| const b = () => constant; | |
| b satisfies string; | |
| } | |
| } | |
| 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" | |
| } | |
| } | |
| const obj1 = { a: 5 }; | |
| const obj2: { prop: { a: number } } = { prop: obj1 } | |
| obj1.a = 6; | |
| obj1.a = "hello"; | |
| const proxy1 = new Proxy({}, { get(_target, prop, receiver) { return prop } }); | |
| proxy1 satisfies { a: "a", b: "b" }; | |
| proxy1 satisfies { c: "d" }; | |
| 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; | |
| }; | |
| () => { | |
| const a = 2 | |
| { | |
| const a = 3; | |
| a satisfies 3; | |
| } | |
| a satisfies 2; | |
| const a = 3; | |
| const x = { a: 2, b: 3 } | |
| delete x.b; | |
| const b = x.b; | |
| const obj = { a: 1, b: 2 }; | |
| obj.a = 2; obj.c = 6; obj.b = 4; | |
| obj satisfies boolean; | |
| 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 | |
| function func(a: number) { | |
| a satisfies string | |
| } | |
| const 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; | |
| class X { | |
| method() { | |
| return this; | |
| } | |
| } | |
| const { method } = new X(); | |
| method(); | |
| function eqNarrow(a: string) { | |
| const b = a; | |
| if (b === "hi") { | |
| a satisfies "hello" | |
| } | |
| } | |
| const my_obj: { a: number } = { a: 2 } | |
| my_obj.a = "hello world" | |
| }; | |
| () => { | |
| const a = 2 | |
| { | |
| const a = 3; | |
| a satisfies 2; | |
| } | |
| let x = {}; x.something = null; x[4] = null; x["eight"] = null; x["2"] = null; | |
| x satisfies string; | |
| const obj = { get prop() { return 2 } }; | |
| obj.prop = "hi"; | |
| obj.prop satisfies 2; | |
| type MyObject = { foo: number, bar: number }; | |
| void function declare_variables(condition: boolean) { | |
| const b: MyObject = { foo: 1, ...{ bar: 2, invalid: 3 } }; | |
| const c: MyObject = { foo: 1, ...(condition ? { bar: 2, non_existent: 3 } : { }) } | |
| } | |
| function func(): string { | |
| return 2 | |
| } | |
| function MyClass(value) { | |
| this.value = value | |
| } | |
| MyClass.prototype.other = 2; | |
| const object = new MyClass("hi"); | |
| object.value satisfies "hi"; | |
| object.other satisfies "hello"; | |
| let global: number = 0; | |
| class X { | |
| [global++] = "b"; | |
| } | |
| global satisfies 0; | |
| (new X)[0] satisfies "a"; | |
| (new X, new X); | |
| global satisfies string; | |
| }; | |
| () => { | |
| let my_obj = { a: 3 } | |
| const a = my_obj.a | |
| const b = my_obj.b | |
| const obj = { prop: 1 }; | |
| // Fine | |
| obj.non_existent = 6; | |
| function func(param: { prop: number }) { | |
| param.notProp = 5; | |
| } | |
| const x: 4 = 2 + 3 | |
| const y: 6 = 2 * 3 | |
| const z: 8 = (2 * 3) - 2 | |
| const object = { a: { b: { c: 2 } } } | |
| const { a: { b: { c: d } } } = object | |
| d satisfies 1; | |
| let global: number = 0; | |
| class X { | |
| property = ++global; | |
| } | |
| (new X()).property satisfies string; | |
| (new X()).property satisfies 2; | |
| (new X()).property satisfies boolean; | |
| }; | |
| () => { | |
| let a = 2; | |
| const obj = { | |
| x: 5, | |
| set value(this: { x: number }, v) { | |
| this.x = v; | |
| } | |
| } | |
| obj.value = "some value"; | |
| obj.x satisfies 5; | |
| const x: 2 = 2 & 3 | |
| const y: 6 = 2 ^ 7 | |
| const z: 14 = 8 | 4 | |
| 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; | |
| let b: number = 0 | |
| function doThing(a: number = (b += 2)) { | |
| return a | |
| } | |
| doThing(7); | |
| b satisfies 0; | |
| doThing(); | |
| b satisfies 1; | |
| class X { | |
| a = 2 | |
| } | |
| (new X).a satisfies 3 | |
| }; | |
| () => { | |
| let a = 2; | |
| const obj = { | |
| x: 5, | |
| set value(v) { | |
| a = v; | |
| } | |
| } | |
| obj.value = "some value"; | |
| a satisfies 2; | |
| const x: 2 = 3 && 2 | |
| const y: 6 = 3 && false | |
| const z: false = true || 4 | |
| function func<T extends boolean>(condition: T) { | |
| if (condition) { | |
| return 4 | |
| } else { | |
| return 3 | |
| } | |
| } | |
| func satisfies string; | |
| 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; | |
| class X { | |
| static a = 2 | |
| } | |
| X.a satisfies 3 | |
| }; | |
| () => { | |
| function a() { } | |
| class B { } | |
| let c = class { } | |
| a.name satisfies "a" | |
| B.name satisfies "B" | |
| c.name satisfies "sea" | |
| const 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 | |
| const x: (a: string) => number = a => a.to; | |
| 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; | |
| class X { | |
| static x = 2; | |
| static { | |
| const property: 4 = ++this.x; | |
| } | |
| } | |
| X.x satisfies 3; | |
| }; | |
| () => { | |
| const obj = {}; | |
| Object.defineProperty(obj, 'property', { | |
| value: 42, | |
| writable: false, | |
| }); | |
| obj.property satisfies string; | |
| obj.property = 70; | |
| interface MyObject { property: string } | |
| const a: MyObject = { property: "hello", another: 2 } | |
| function x() { | |
| getString(3) | |
| } | |
| function y() { | |
| getString("something") satisfies string; | |
| } | |
| function getString(param: string): string { | |
| return "hi" | |
| } | |
| function func(a: number) {} | |
| func("hello world"); | |
| class X { a: number = 2 } | |
| class Y { a: number = 2} | |
| function doThingWithX(x: X) {} | |
| doThingWithX(new X()); | |
| doThingWithX(new Y()); | |
| }; | |
| () => { | |
| 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; | |
| let a = 5, b = 6; | |
| a++; | |
| a satisfies 4; | |
| b *= 4; | |
| b satisfies 23; | |
| function func(p1: number, p2: string) {} | |
| func(4); | |
| const x = "hi" | |
| x(); | |
| type X<T> = T; | |
| 2 satisfies X<string>; | |
| }; | |
| () => { | |
| const obj = {}; | |
| let b = 0; | |
| Object.defineProperty(obj, 'property', { | |
| get: () => b, | |
| }); | |
| obj.property satisfies 0; | |
| b++; | |
| obj.property satisfies string; | |
| function func(p1: number) {} | |
| func(4, "extra"); | |
| let a: number = 2 | |
| function runFunctionTwice(func: () => void) { | |
| func() | |
| func() | |
| } | |
| a satisfies 2 | |
| runFunctionTwice(() => { a++ }) | |
| a satisfies string | |
| function getX() { | |
| return x | |
| } | |
| getX satisfies () => number; | |
| getX(); | |
| let x: number = 5; | |
| type X = 2 & "hi"; | |
| type Y = string & number; | |
| }; | |
| () => { | |
| const obj = {}; | |
| Object.defineProperty(obj, 'property', { value: 6 }); | |
| Object.defineProperty(obj, 'property', { value: "hi" }); | |
| void function declare_variables(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 | |
| } | |
| 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 | |
| const x = [1]; | |
| x.push("hi"); | |
| x[1] satisfies 3; | |
| x.length satisfies 4; | |
| type X<T> = T; | |
| const b: X = 2; | |
| }; | |
| () => { | |
| const obj = { a: "something" }; | |
| Object.defineProperty(obj, 'b', { value: 42 }); | |
| Object.getOwnPropertyDescriptor(obj, 'a') satisfies string; | |
| Object.getOwnPropertyDescriptor(obj, 'b').writable satisfies false; | |
| 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 | |
| const x: Array<number> = [1] | |
| x.push("hi"); | |
| 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; | |
| }; | |
| () => { | |
| const obj = { a: 1 }; | |
| Object.assign(obj, { b: 2, c: 3 }); | |
| obj satisfies string; | |
| let a: number = 0 | |
| function func(c: number) { | |
| a = c | |
| } | |
| func(4) | |
| let b: 2 = a | |
| interface X { | |
| a: string, | |
| b: boolean | |
| } | |
| const x: X = { a: 2, b: false } | |
| }; | |
| () => { | |
| const obj = {} | |
| let result = Object.freeze(obj); | |
| (obj === result) satisfies true; | |
| obj.property = 2; | |
| Object.isSealed(obj) satisfies true; | |
| function func(obj: { prop: number }) { | |
| return obj.prop | |
| } | |
| func({ get prop() { return b } }); | |
| let b: number = 0; | |
| let a: number = 0 | |
| function conditional(v: string) { | |
| if (v === "value") { | |
| a++ | |
| } | |
| } | |
| conditional("x") | |
| a satisfies 2 | |
| conditional("value") | |
| a satisfies 3 | |
| getFive() satisfies 4; | |
| function getFive() { | |
| return 5 | |
| } | |
| let x: X = { a: 3 } | |
| interface X { | |
| a: 2 | |
| } | |
| }; | |
| () => { | |
| const obj = { a: 2 } | |
| let result = Object.seal(obj); | |
| (obj === result) satisfies true; | |
| // Allowed | |
| obj.a = 4; | |
| // Not allowed | |
| obj.property = 2; | |
| Object.isSealed(obj) satisfies true; | |
| Object.isFrozen(obj) satisfies false; | |
| function newObject() { | |
| return { prop: 2 } | |
| } | |
| const a = newObject(), b = newObject(); | |
| const c = a; | |
| (a === c) satisfies false; | |
| (a === b) satisfies string; | |
| 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); | |
| } | |
| const x = 2 | |
| const y = { x } | |
| y.x satisfies 3 | |
| interface X { | |
| a: string, | |
| b: string | |
| } | |
| "a" satisfies keyof X; "b" satisfies keyof X; "c" satisfies keyof X; | |
| }; | |
| () => { | |
| const obj = { a: 2 } | |
| let result = Object.preventExtensions(obj); | |
| (obj === result) satisfies true; | |
| // Allowed | |
| obj.a = 4; | |
| // Not allowed | |
| obj.property = 2; | |
| Object.isFrozen(obj) satisfies false; | |
| Object.isSealed(obj) satisfies false; | |
| let 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; | |
| let a = false, b = 4; | |
| a ||= b++; | |
| a satisfies 3; | |
| b ||= (b = 10); | |
| b satisfies string; | |
| type X<T> = T extends { a: infer I extends string } ? I : string; | |
| void function declare_variables(a: X<{ a: 4 }>, b: X<{ a: "hello" }>) { | |
| a satisfies number; | |
| b satisfies "hello" | |
| } | |
| }; | |
| () => { | |
| const obj = { | |
| a: 4, | |
| getA(this: { a: any }) { | |
| return this.a | |
| } | |
| } | |
| obj.a = 5; | |
| obj.getA() satisfies 6; | |
| 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; | |
| interface BoxString<T extends string> { | |
| inner: T | |
| } | |
| let x: BoxString<string, number>; | |
| type Pick<T, K extends keyof T> = { [P in K]: T[P] }; | |
| interface X { | |
| a: number | |
| b: string | |
| c: string | |
| } | |
| void function declare_variables(y: Pick<X, "b" | "c">) { | |
| ({ 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">); | |
| y.b satisfies string; | |
| y.a | |
| } | |
| }; | |
| () => { | |
| const obj: { a: number } = { a: 2 } | |
| function func(value: number) { | |
| obj.a = value | |
| } | |
| obj.a satisfies 2 | |
| func(4) | |
| obj.a satisfies 3 | |
| let a: number = 1, i: number = 0; | |
| while (i < 5) { | |
| a *= 2; | |
| i++; | |
| } | |
| a satisfies 8; | |
| const x: "\"" = '"'; | |
| const y: "Hi" = `Hello\``; | |
| type PrefixKeys<T> = { [P in ((keyof T) & string) as `property_${P}`]: T[P] }; | |
| interface X { | |
| a: number | |
| } | |
| void function declare_variables(x: PrefixKeys<X>) { | |
| x.property_a satisfies number; | |
| x.property_b | |
| } | |
| }; | |
| () => { | |
| function add_property(obj: { prop: number }) { | |
| obj.prop += 2; | |
| } | |
| const obj = { prop: 4 }; | |
| add_property(obj); | |
| obj.prop satisfies 8; | |
| 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; | |
| let a: number = 1, i: number = 0; | |
| while (i++ < 5) { | |
| a *= 2; | |
| } | |
| a satisfies 8; | |
| class X { | |
| constructor(value) { | |
| this.value = value | |
| } | |
| } | |
| const x = new X(4) | |
| x.value satisfies string | |
| }; | |
| () => { | |
| function dewete(param: { prop?: string }) { | |
| const { prop } = param; | |
| delete param.prop; | |
| return prop | |
| } | |
| const obj = { prop: "hi" }; | |
| dewete(obj); | |
| obj.prop; | |
| let a: number = 0 | |
| const func = condition => condition || ++a; | |
| func(true); | |
| a satisfies 0; | |
| func(false) satisfies 1; | |
| a satisfies 2; | |
| let global: number = 0; | |
| class X { | |
| prop1 = ++global; | |
| constructor() { | |
| this.prop2 = ++global; | |
| } | |
| } | |
| const x = new X(); | |
| x.prop1 satisfies string; | |
| x.prop2 satisfies boolean; | |
| }; | |
| () => { | |
| function func(param: boolean) { | |
| let a = 2; | |
| if (param) { | |
| a = 3; | |
| return a; | |
| } else { | |
| a = 7; | |
| } | |
| a satisfies string; | |
| } | |
| let a: number = 0; | |
| do { | |
| a++ | |
| } while (a < 3) | |
| a satisfies 8; | |
| const obj = { a: 2 }; | |
| ("a" in obj) satisfies string; | |
| ("b" in obj) satisfies true; | |
| 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 | |
| }; | |
| () => { | |
| let a: string = ""; | |
| for (let i: number = 0; i < 10; i++) { | |
| a = a + i; | |
| } | |
| a satisfies number; | |
| void function declare_variables(x: NotNotANumber) { | |
| // True regardless of | |
| function func(a: number) { | |
| return a ** 0 | |
| } | |
| func satisfies string; | |
| (x ** 1 === x) satisfies true | |
| } | |
| const x = new X; | |
| class X { } | |
| const obj = { a: 1, b: 2, c: 3 }; | |
| obj satisfies { [s: string]: number }; | |
| obj satisfies { [s: string]: boolean }; | |
| }; | |
| () => { | |
| void function declare_variables(i: number) { | |
| let a: number = 0; | |
| while (a < i) { | |
| a++ | |
| } | |
| a satisfies string | |
| } | |
| function func(a: number, b: boolean) { | |
| const x = !a; | |
| const y = ~b; | |
| (!b), (~a); | |
| } | |
| class X { } | |
| const x = X(); | |
| function func1(p: { a: string, b: string }) { | |
| func2(p) | |
| } | |
| function func2(p: readonly { a: string }) { } | |
| const obj = Object.freeze({ a: "hi" }); | |
| func2(obj); | |
| }; | |
| () => { | |
| let a: number = 0; | |
| while (a++ < 1_000_000) {} | |
| a satisfies string; | |
| void function declare_variables(someNumber: number) { | |
| function func() {} | |
| (typeof 5) satisfies "number"; | |
| (typeof "hi") satisfies "string"; | |
| (typeof func) satisfies "function"; | |
| (typeof someNumber) satisfies "function" | |
| } | |
| let 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; | |
| interface MyObject { | |
| a(b: string): any; | |
| } | |
| const obj: MyObject = { | |
| a(b) { | |
| b satisfies number; | |
| } | |
| } | |
| }; | |
| () => { | |
| let a: number = 2, i: number = 0; | |
| while (i++ < 10) { | |
| a *= 2; | |
| if (a > 5) { | |
| break; | |
| } | |
| } | |
| a satisfies 2; | |
| interface X { | |
| a: string | |
| b: string | |
| } | |
| function func(x: X | null) { | |
| x.a; | |
| x?.b satisfies number; | |
| } | |
| // Perfectly fine | |
| const x: (a: number) => string = (p: string | number) => "hi" | |
| // Bad | |
| const y: (a: number | string) => string = (p: number) => "hi" | |
| const obj = { a: 2 }; | |
| const proxy1 = new Proxy(obj, { }); | |
| proxy1.a = 6; | |
| obj.a satisfies 6; | |
| proxy1.a satisfies string; | |
| }; | |
| () => { | |
| let a: number = 2, i: number = 0; | |
| while (i++ < 10) { | |
| if (i % 2) { | |
| continue; | |
| } | |
| a *= 2; | |
| } | |
| a satisfies 2; | |
| type X = string; | |
| { | |
| type X = number; | |
| const a: X = "hello world"; | |
| } | |
| function func<YEA>() {} | |
| type B = YEA; | |
| // Perfectly fine | |
| const x: (a: number, b: string) => string = (p: number) => "hi" | |
| // Bad | |
| const y: (a: string) => string = (p: number, q: string) => "hi" | |
| }; | |
| () => { | |
| const object = { a: 1, b: 2 } | |
| const { a, b } = object | |
| a satisfies 1; b satisfies string; | |
| const x: (a: number) => number = p => 4; | |
| const y: (a: number) => number = p => "a number" | |
| void function declare_variables(func: <T>() => T | string) { | |
| func<number>() satisfies string | number; | |
| func<never>() satisfies boolean | |
| } | |
| interface X { | |
| a: number | |
| b: X | |
| } | |
| const myObject = { a: 2 }; | |
| myObject satisfies X; | |
| myObject.b = myObject; | |
| myObject satisfies X; | |
| }; | |
| () => { | |
| 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; | |
| type X = Y; | |
| type Y = X; | |
| // test usage doesn't blow up subtyping | |
| const x: X = 2; | |
| function func(a: `a${string}`, b: `b${string}`, c: string) { | |
| const res1 = a === b; | |
| const res2 = (b === c) satisfies string; | |
| } | |
| }; | |
| () => { | |
| type X = number; | |
| const a: Y = 2; | |
| void function declare_variables(func: <T>(a: T, b: NoInfer<T>) => T) { | |
| func("hi", "hello") satisfies number | |
| } | |
| const x: Record<"test", boolean> = { no: false }, | |
| y: Record<"test", boolean> = { test: 6 }, | |
| z: Record<"test", boolean> = { test: false }; | |
| }; | |
| () => { | |
| type X = number; | |
| const a: X<number> = 2; | |
| function func<T>(a: T) {} | |
| func<number>("hello world"); | |
| function x(p: { readonly a: string, b: string }) { | |
| p.a = "hi"; | |
| p.b = "hi"; | |
| } | |
| }; | |
| () => { | |
| const a: Uppercase<"something" |"hi"> = "HI"; | |
| const b: Uppercase<string> = "hi" | |
| void function declare_variables(func: () => any) { | |
| func<string>() | |
| } | |
| const x = [1, 2, 3]; | |
| x.map(a => (a satisfies string, 2)); | |
| }; | |
| () => { | |
| function func(param: boolean | string | number) { | |
| if (typeof param === "boolean") { | |
| return 5 | |
| } | |
| param satisfies null; | |
| } | |
| const x = { a: 3 }; | |
| Object.setPrototypeOf(x, { a: 5, b: 2 }); | |
| x.a satisfies 3; | |
| x.b satisfies string; | |
| const obj = Object.setPrototypeOf( | |
| {}, | |
| Math.random() ? { a: 2 } : { get a() { return 0 } } | |
| ); | |
| const result = 'a' in obj; | |
| result satisfies string; | |
| }; | |
| () => { | |
| function func(param: Array<string> | string) { | |
| if (param instanceof Array) { | |
| param satisfies null; | |
| } | |
| } | |
| 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; | |
| }; | |
| () => { | |
| function func(param: any) { | |
| if (param instanceof Array) { | |
| param satisfies null; | |
| } | |
| } | |
| 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); | |
| }; | |
| () => { | |
| function func(param: boolean) { | |
| let a = param; | |
| const inner = (value: boolean) => a = value; | |
| if (a) { | |
| inner(false); | |
| a satisfies null; | |
| } | |
| } | |
| const obj = { prop: 2 }; | |
| console.log(obj.a.b.c); | |
| function x() { | |
| return y | |
| } | |
| x().nothing | |
| }; | |
| () => { | |
| function func(param: number | Array<string>) { | |
| if (Array.isArray(param)) { | |
| param satisfies null; | |
| } | |
| } | |
| 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; | |
| }; | |
| () => { | |
| function func(param: number) { | |
| if (param !== param) { | |
| param satisfies string; | |
| } | |
| // Derives from `!==` | |
| if (Number.isNaN(param)) { | |
| param satisfies null; | |
| } | |
| } | |
| function x(a /** string */) { | |
| a satisfies number | |
| } | |
| const c /** number */ = "hello" | |
| }; | |
| () => { | |
| function func(a: boolean) { | |
| const x = a ? 1 : 2; | |
| if (x === 1) { | |
| a satisfies "hi" | |
| } | |
| } | |
| interface X { a: number } | |
| const x = { a: 1, b: 2 }; | |
| x satisfies Exclusive<X>; | |
| ({ a: 6 } satisfies Exclusive<X>); | |
| }; | |
| () => { | |
| function func(value: any) { | |
| function isNumber() { return typeof value === "number" } | |
| if (isNumber()) { | |
| value satisfies string | |
| } | |
| } | |
| }; | |
| () => { | |
| function register(a: Literal<string>) { | |
| // ... | |
| } | |
| register("something") | |
| // `document.title` is an unknown string, non-literal | |
| register(document.title); | |
| function func(param: object) { | |
| const obj = { a: 2 }; | |
| const obj1: Literal<object> = obj; | |
| const obj2: Literal<object> = param; | |
| } | |
| }; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment