Destructuring a function parameter object and …res

2020-04-02 06:34发布

I'd like to write a function that takes an object parameter and captures all the remaining parameters in a variable. The goal is to allow the function to receive named parameters (as opposed to positional parameters), some of them optional, and set default values in the function. So, in pseudo code something like this:

interface IMyProps {
  a: string
  b?: number
}

const myfun1 = (p: {a: string, b?:number, ...rest}) => {
  const {a, b = 'hello'} = p;
}

What would be the best way to achieve this in Typescript 2.0?

标签: typescript
2条回答
家丑人穷心不美
2楼-- · 2020-04-02 07:05

You can use destructuring assignment directly in the function arguments:

interface IMyType { 
    a: number;
    b: number;
    c: number;
    d: number;
    [k: string]: number; // use this if you don't know the name of the properties in 'rest'
}

const obj: IMyType = { a: 1, b: 2, c: 3, d: 4 }

// Normal destructuring
const { a, b, ...rest } = obj;
console.log(rest); // {c: 3, d: 4}

// Directly in function arguments
const fn = ({ a, b, ...rest }: IMyType) => { console.log(rest); }

console.log(fn(obj)); // {c: 3, d: 4}
查看更多
混吃等死
3楼-- · 2020-04-02 07:12

I think object destructing with the rest operator in TypeScript corresponds to the index signature on the type of the destructured object if you have pulled off all the explicitly named properties already. That means you would have the same restriction where the types of the rest properties would have to be at least as wide as the union of all the explicitly labeled properties. In your case, you could extend IMyProps with an index signature like this:

interface IMyPropsWithIndex {
  a: string
  b?: number
  [k: string]: string | number | undefined
}

since the type of a is string and the type of b is number | undefined. You could add more stuff to the union but you couldn't make it something narrower like string. If that's okay with you, then the way to do destructuring would be something like this:

const myfun1 = (p: IMyPropsWithIndex) => {
  const { a, b = 'hello' , ...rest } = p;
  a; // string
  b; // number | 'hello'
  rest; // {[k: string]: string | number | undefined}
}

If you inspect the types of the variables, you get something like the above.

That's probably the best you can do with typing the rest properties. Ideally you could use generics, but you can't use the rest/spread operator with generics as of now, and there is an open issue in GitHub tracking this.

Hope that helps. Good luck.

查看更多
登录 后发表回答