1

I am trying to type correctly following code:

interface SomeObject {
  fn1: (params: { a: string, b: object }) => void,
  fn2: (params: { c: number }) => number,
  fn3: () => number
}

type Methods = keyof SomeObject;

let someObject: SomeObject = {
  fn1: ({ a, b }) => console.log(a, b),
  fn2: ({ c }) => c,
  fn3: () => 1
}

const fn = <T extends Methods>({ method, parameters }: {
  method: T,
  parameters: Parameters<SomeObject[T]>
}) => {
  const _method = someObject[method]

  _method(parameters[0]);
}

fn({ method: 'fn1', parameters: [{a:'str', b:{}}] });

The problem that I encountered is that _method gets a following type:

const _method: (params: {
    a: string;
    b: object;
} & {
    c: number;
}) => number | void

So it takes an intersection of all possible parameters and thus making it impossible to use the fn({ method, parameters }) notation. Is there any workaround? (without using as or any)

You can find TypeScript playground here.

1 Answer 1

1

Here you have a small trick how to make it work:

interface SomeObject {
  fn1: (params: { a: string, b: object }) => void,
  fn2: (params: { c: number }) => number,
  fn3: () => number
}

type Methods = keyof SomeObject;

const someObject: SomeObject = {
  fn1: ({ a, b }) => console.log(a, b),
  fn2: ({ c }) => c,
  fn3: () => 1
};

type Args<T extends Methods> = {
  method: T,
  parameters: Parameters<SomeObject[T]>
}
const fn = <T extends Methods>(method: T, callback: (method: SomeObject[T]) => any) => callback(someObject[method]);

fn('fn1', (method) => method({ a: 'sdf', b: {} })) // ok
fn('fn1', (method) => method({ a: 2, b: {} })) // expected error

fn('fn2', (method) => method({ c:42})) // ok
fn('fn2', (method) => method({ c:'42'})) // expected error

fn('fn3', (method) => method()) //ok
fn('fn3', (method) => method(2)) //expected error

Playground link

I'm not specialist in type system theory, but I'd willing to bet the the problem caused by contravariance.

I will happy to hear any explanations )

Sign up to request clarification or add additional context in comments.

1 Comment

thank you for your response. I decided to open a bug github.com/microsoft/TypeScript/issues/42818 to seek the official explanation

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.