简体   繁体   中英

How can I make a function parameter respect an object type in TypeScript?

I have the following code:

const someCollection = {};

/**
 * @param id
 * @param callback The callback will be given an object with keys `a1` (of type "string") and `a2` (of type "number").
 */
const addSomething = (id, callback) => {
  someCollection[id] = { callback };
};

const getSomething = (id) => {
  return someCollection[id];
};

addSomething("someId", ({ arg1, arg2 }) => {
  console.log(arg1, arg2);
});

const something = getSomething("someId");

something.callback({ arg1: "hey", arg2: 2 });

If you take a look at addSomething 's comment about the callback param, it says that it would like to receive a callback with two parameters, in the shape of: arg1: string, arg2: number , together with the id , this forms an item in our collection. To note that we'll put the callback under the callback index inside our collection. Let's go ahead and addSomething and you can tell it all works once we retrieve it and print it all. Our output should be hey, 2 . Well, let's write this in TS:

const someCollection: { [index: string]: any } = {};

type CallbackType = {
  new(
  a1: string,
  a2: number
  ): void
};

function addSomething(id: string, callback: CallbackType): void {
  console.log( `${type.a1} + ${type.a2}`);
}


addSomething('someId', ({a1: 'hey', a2: 2 }))

Well, it doesn't work. I can tell the code is wrong, I just don't know how to fix it. The first cue is that TS probably doesn't know how to handle "named arguments" and when I addSomething , I'm really just passing a function with an object as its one, single parameter . The second cue is that callback is just...well, uh...not sure? It surely isn't a function.

In short, I'd like for anyone that passes a callback to addSomething to respect the rules of the CallbackType type and pass named arguments, arg1 and arg2 respectively, with the correct types.

What am I not understanding here?

Here is a solution:

interface Something {
    callback: SomethingCallback
}

type SomethingCallback = (obj: {arg1: string, arg2: number}) => void;

const someCollection: { [id: string]: Something } = {};

const addSomething = (id: string, callback: SomethingCallback) => {
  someCollection[id] = { callback };
};

const getSomething = (id: string) => {
  return someCollection[id];
};

addSomething("someId", ({ arg1, arg2 }) => {
  console.log(arg1, arg2);
});

const something = getSomething("someId");

something.callback({ arg1: "hey", arg2: 2 });

An explanation

At first, we declare the types we need. An interface Something that will be stored in the collection. This is an object that contains a key callback and a value of type SomethingCallback .

interface Something {
  callback: SomethingCallback
}

The type SomethingCallback represents a function that takes one parameter. The parameter must contain 2 keys arg1 of type string , and arg2 of type number :

type SomethingCallback = (obj: {arg1: string, arg2: number}) => void;

Here is how to declare the type of someCollection . It is an object used as a dictionary. In TS this pattern is called an index signature :

const someCollection: { [id: string]: Something } = {};

Then, all you have to do is to use the types as annotations in addSomething and getSomething parameters.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM