Created
October 10, 2023 11:36
-
-
Save peterhudec/c0fdda0add399c961a29429c92199198 to your computer and use it in GitHub Desktop.
TypeScript Generics Proposal
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
| type Func = (...args: any) => any | |
| type FP = <T>(...params: [T, T]) => void | |
| type FPA = <T>(a: [T, T]) => void | |
| type FPO = <T>(o: {x: T, y: T}) => void | |
| type FPF = <T extends Func>(f: T, p: Parameters<T>) => void | |
| type FNested = <T>(x: T, y: T) => | |
| <TT>(x: TT, y: TT, z: [T, TT]) => void | |
| type FRA = <T>() => [T, T] | |
| type FRO = <T>() => {x: T, y: T} | |
| type FRF = <T extends Func>() => {func: T, args: Parameters<T>} | |
| /* | |
| It would be nice if we could do the same with (readonly?) arrays and objects | |
| type A = <T>[T, T] | |
| const a: A = [ | |
| 'abc', | |
| 123, | |
| ^^^ Type 'number' is not assignable to type 'string'.(2322) | |
| ] | |
| type O = <T>{x: T, y: T} | |
| const o: O = { | |
| x: 'abc', | |
| y: 123, | |
| ^ Type 'number' is not assignable to type 'string'.(2322) | |
| } | |
| type AF = <T extends Func>[T, Parameters<T>] | |
| const af: AF = [ | |
| (s: string, n: number) => null, | |
| ['abc', 'def'], | |
| ^^^^^ Type 'string' is not assignable to type 'number'.(2322) | |
| ] | |
| type OF = <T extends Func>{func: T, args: Parameters<T>} | |
| const of: OF = { | |
| func: (s: string, n: number) => null, | |
| args: ['abc', 'def'], | |
| ^^^^^ Type 'string' is not assignable to type 'number'.(2322) | |
| } | |
| type ANested = <T>[T, <TT>[TT, [T, TT]]] | |
| type ONested = <T>{x: T, y: <TT>{z: [T, TT]}} | |
| */ | |
| type FPParams = Parameters<FP> // [unknown, unknown] | |
| // Would be nice if it was <T>[T, T] | |
| type FPAParams = Parameters<FPA> // [a: [unknown, unknown]] | |
| // Would be nice if it was <T>[a: [T, T]] | |
| type FPOParams = Parameters<FPO> // [o: {x: unknown, y: unknown}] | |
| // Would be nice if it was <T>[o: {x: T, y: T}] | |
| type FPFParams = Parameters<FPF> // [f: Func, p: any] | |
| // Would be nice if it was <T extends Func>[f: T, p: Parameters<T>] | |
| type FNestedParams = Parameters<FNested> // [a: [unknown, {x: {y: [unknown]}}]] | |
| // Would be nice if it was // <T>[a: [T, {x: {y: [T]}}]] | |
| type FRAReturnType = ReturnType<FRA> // [unknown, unknown] | |
| // Would be nice if it was <T>[T, T] | |
| type FROReturnType = ReturnType<FRO> // {x: unknown, y: unknown} | |
| // Would be nice if it was <T>{x: T, y: T} | |
| type FRFReturnType = ReturnType<FRF> // {func: Func, args: any} | |
| // Would be nice if it was <T extends Func>{func: T, args: Parameters<T>} | |
| declare const fp: FP | |
| declare const fpa: FPA | |
| declare const fpo: FPO | |
| declare const fNested: FNested | |
| declare const fra: FRA | |
| declare const fro: FRO | |
| declare const fpf: FPF | |
| declare const frf: FRF | |
| fp('abc', 123) | |
| // ^^^ Type 'number' is not assignable to type 'string'.(2322) | |
| const fpParams: Parameters<FP> = ['abc', 123] | |
| // ^^^ Would be nice to have the same error here | |
| fpa(['abc', 123]) | |
| // ^^^ Type 'number' is not assignable to type 'string'.(2322) | |
| const fpaParams: Parameters<FPA> = [['abc', 123]] | |
| // ^^^ Would be nice to have the same error here | |
| const fraRetVal: ReturnType<FRA> = ['abc', 123] | |
| // ^^^ Would be nice to have the same error here | |
| fNested(['abc', {x: {y: [123]}}]) | |
| // ^^^ Type 'number' is not assignable to type 'string'.(2322) | |
| const fNestedParams: Parameters<FNested> = [['abc', {x: {y: [123]}}]] | |
| // ^^^ Would be nice to have the same error here | |
| fpo({x: 123, y: 'abc'}) | |
| // ^ Type 'string' is not assignable to type 'number'.(2322) | |
| const fpoParams: Parameters<FPO> = [{x: 'abc', y: 123}] | |
| // ^ Would be nice to have the same error here | |
| const froRetVal: ReturnType<FRO> = {x: 'abc', y: 123} | |
| // ^ Would be nice to have the same error here | |
| fpf((s: string, n: number) => null, ['foo', '123']) | |
| // ^^^^^ Type 'string' is not assignable to type 'number'.(2322) | |
| const fpfParams: Parameters<FPF> = [(s: string, n: number) => null, ['foo', '123']] | |
| // ^^^^^ Would be nice to have the same error here | |
| // When the function result is assigned to an untyped variable, | |
| // the relationship between the two tuple items is lost. | |
| const fraResult = fra() // [unknown, unknown] | |
| const a: [string, number] = fraResult | |
| // ^ | |
| // Type '[unknown, unknown]' is not assignable to type '[string, number]'. | |
| // Type at position 0 in source is not compatible with type at position 0 in target. | |
| // Type 'unknown' is not assignable to type 'string'.(2322) | |
| // But when assigning the function call directly, the relationship between the two items seems to be preserved | |
| const b: [string, number] = fra() // const fra: <string | number>() => [string | number, string | number] | |
| // ^ | |
| // Type '[string | number, string | number]' is not assignable to type '[string, number]'. | |
| // Type at position 0 in source is not compatible with type at position 0 in target. | |
| // Type 'string | number' is not assignable to type 'string'. | |
| // Type 'number' is not assignable to type 'string'.(2322) | |
| // Same with objects | |
| const froResult = fro() // const fro: <unknown>() => {x: unknown, y: unknown} | |
| const c: {x: string, y: number} = froResult | |
| // ^ | |
| // Type '{ x: unknown; y: unknown; }' is not assignable to type '{ x: string; y: number; }'. | |
| // Types of property 'x' are incompatible. | |
| // Type 'unknown' is not assignable to type 'string'.(2322) | |
| const y: {x: string, y: number} = fro() // const fro: <string | number>() => {x: string | number; y: string | number} | |
| // ^ | |
| // Type '{ x: string | number; y: string | number; }' is not assignable to type '{ x: string; y: number; }'. | |
| // Types of property 'x' are incompatible. | |
| // Type 'string | number' is not assignable to type 'string'. | |
| // Type 'number' is not assignable to type 'string'.(2322) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment