3

I have a {string: Function} map a:

const a: A = {
    foo: (x: string) => 8,
    bar: (y: number, z: boolean) => 6,
}

I then transform it such that every mapped function has a different type of return value:

const b: B = {
    foo: (x: string) => (8).toString(),
    bar: (y: number, z: boolean) => (6).toString(),
}

In TypeScript, is there any way to describe type B as derived from A, in my dream world, I'd like to be able to do:

type A = {
    foo: (string) => number
    bar: (number, boolean) => number
}
type B = {
    [K in keyof A]: (E in argsof A[K]) => string
}

2 Answers 2

5

Dreams come true in Typescript :)

You can achieve this in Typescript 3.0 using conditional types and Tuples in rest parameters and spread expressions:

type A = {
    foo: (s: string) => number
    bar: (n: number, b: boolean) => number
}


type ArgumentTypes<T extends (...a: any[]) => any> = T extends (...a: infer A) => any ? A : []; 
type B = {
    [K in keyof A]:  (...a:ArgumentTypes<A[K]>) => string 
}

let b: B;
b.foo("") // works
b.foo(1) // error
Sign up to request clarification or add additional context in comments.

Comments

3

You can achieve this using the built in Parameters<T> type as of Typescript 3.1:

type B = {
  [K in keyof A]:  (...a: Parameters<A[K]>) => string
}

This isn't explicitly documented in the Typescript docs on conditional types but similar conditional types are, like ReturnType<T>, you can see them all in the source.

With this in mind we could go a step further and relate B to the return type of our transforming function using ReturnType<T>:

const transformingFunction: (n: number) => string = (n: number) => n.toString();

type B = {
  [K in keyof A]:  (...a: Parameters<A[K]>) => ReturnType<typeof transformingFunction>
}

So now, if we want to change the return type of our transforming function, it can be done in one place, i.e. on the function itself without breaking the signature of B.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.