Skip to content

Instantly share code, notes, and snippets.

@Offirmo
Last active January 2, 2023 07:14
Show Gist options
  • Save Offirmo/c6a67f81526eb2f43ae600523747ceaf to your computer and use it in GitHub Desktop.
Save Offirmo/c6a67f81526eb2f43ae600523747ceaf to your computer and use it in GitHub Desktop.
[typescript conditional types playground] #typescript
// type tester for generics
type ImmutablePrimitive = undefined | null | boolean | string | number | Function
interface EmptyStruct { }
// https://www.typescriptlang.org/docs/handbook/2/functions.html#other-types-to-know-about
//type T = any
//type T = unknown
//type T = void
//type T = undefined
//type T = object
//type T = never
//type T = null
//type T = boolean
type T = string
//type T = number
//type T = Function
//type T = () => number
//type T = string[]
//type T = Map<string, number>
//type T = { foo: number[] }
// // any unkn undefined object null string Function string[] Map<s,n> Struct
type KeyofT = keyof T // || nv nv nv ... nv x x
type ValuesOfT = T[keyof T] // any nv nv nv ... nv ... ...
type T_is_any = 0 extends 1 & T ? true : false // any✔
type T_extends_any = T extends any ? true : false // any✔ undef✔ obj✔ nul✔ str✔ fn✔ str[]✔ map✔ stct✔
type any_extends_T_00 = any extends T ? true : false // any✔ ? ? ? ? ? ? ? ?
type any_extends_T_01 = any extends [T] ? true : false // ?? ? ? ? ?
type any_extends_T_10 = [any] extends T ? true : false // any✔ obj✔ str[]✔
type any_extends_T_11 = [any] extends [T] ? true : false // any✔ obj✔ fn✔ str[]✔ map✔ stct✔
type T_extends_unknown = T extends unknown ? true : false // any✔ undef✔ obj✔ nul✔ str✔ fn✔ str[]✔ map✔ stct✔
type unknown_extends_T = unknown extends T ? true : false // any✔
type T_extends_never_00 = T extends never ? true : false // ??
type T_extends_never_01 = T extends [never] ? true : false // ??
type T_extends_never_10 = [T] extends never ? true : false //
type T_extends_never_11 = [T] extends [never] ? true : false //
type never_extends_T = never extends T ? true : false // any✔ undef✔ obj✔ nul✔ str✔ fn✔ str[]✔ map✔ stct✔
type T_extends_string_0 = T extends string ? true : false // ??
type T_extends_ip_00 = T extends ImmutablePrimitive ? true : false // ?? undef✔ nul✔ str✔ fn✔
type T_extends_ip_01 = T extends [ImmutablePrimitive] ? true : false // ??
type T_extends_ip_10 = [T] extends ImmutablePrimitive ? true : false //
type T_extends_ip_11 = [T] extends [ImmutablePrimitive] ? true : false // any✔ undef✔ nul✔ str✔ fn✔
type T_extends_obj_0 = T extends object ? true : false // obj✔
type T_extends_obj_01 = T extends [object] ? true : false //
type T_extends_obj_10 = [T] extends object ? true : false // obj✔ str✔
type T_extends_obj_11 = [T] extends [object] ? true : false // obj✔
type T_extends_array_00 = T extends Array<infer E> ? true : false // ?? str[]✔
type T_extends_map_00 = T extends Map<infer K, infer V> ? true : false // ?? map✔
type T_extends_map_01 = T extends [Map<infer K, infer V>] ? true : false // ??
type T_extends_map_10 = [T] extends Map<infer K, infer V> ? true : false //
type T_extends_map_11 = [T] extends [Map<infer K, infer V>] ? true : false // any✔ map✔
type T_extends_es_00 = T extends EmptyStruct ? true : false // ?? obj✔ str✔ fn✔ str[]✔ map✔ stct✔
type T_extends_es_01 = T extends [EmptyStruct] ? true : false // ??
type T_extends_es_10 = [T] extends EmptyStruct ? true : false // any✔ undef✔ obj✔ nul✔ str✔ fn✔ str[]✔ map✔ stct✔
type T_extends_es_11 = [T] extends [EmptyStruct] ? true : false // any✔ obj✔ str✔ fn✔ str[]✔ map✔ stct✔
export type ImmutableAny = Readonly<any>
export type ImmutableArray<T> = ReadonlyArray<Immutable<T>>
export type ImmutableMap<K, V> = ReadonlyMap<Immutable<K>, Immutable<V>>
export type ImmutableSet<T> = ReadonlySet<Immutable<T>>
export type ImmutableObject<T> = { +readonly [K in keyof T]: Immutable<T[K]> }
export type Immutable<T> = true extends false ? never
//: 0 extends 1 & T ? Readonly<any>
: unknown extends T ? unknown
: T extends Array<infer U> ? ImmutableArray<U> //
: T extends Map<infer K, infer V> ? ImmutableMap<K, V> // any matches by being distributive!!
: T extends Set<infer M> ? ImmutableSet<M> // any matches by being distributive!!
: T extends EmptyStruct ? ImmutableObject<T> // any is distributive + this line is greedy with other container types, must be last!
//: T extends undefined ? undefined
//: T extends null ? null
//: T extends boolean ? boolean
//: T extends string ? string
//: T extends number ? number
//: T extends Function ? Function
: T extends ImmutablePrimitive ? T // any matches by being distributive!! This makes the whole type "ANY"
: never
type I = Immutable<T>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment