嵌套选择定义

huangapple go评论70阅读模式
英文:

Nested Pick definition

问题

在函数的定义中,我只关心选取addresslineOne部分,但据我了解,Pick只允许我深入一层,而不允许我进一步指定我的意思。

是否有一种方法可以在 TypeScript 中实现这个目标?

英文:

If I had an interface with an embedded object such as:

interface IStudent {
    name: string;
    address: {
        lineOne: string;
        lineTwo: string;
    }
}

const getAddressLineOne = (student: Pick<IStudent, 'address'>) => student.address.lineOne;

For the definition of the function, I'd really only care pick the lineOne part of address, but as far as I understand, Pick only allows me to go one level deep, rather than specifying further what I mean.

Is there a way to do this with typescript?

答案1

得分: 3

你可以创建自己的NestedPick类型:

type NestedPick<T, K extends string[]> = T extends object ? {
  [P in Extract<keyof T, K[0]>]: NestedPick<T[P], Tail<K>>
} : T

// 获取元组的尾部
type Tail<T extends any[]> = ((...args: T) => any) extends (head: any, ...tail: infer I) => any
  ? I : never

尚未测试边缘情况,但这可能是一个很好的起点。然后,getAddressLineOne看起来像这样:

const getAddressLineOne = (student: NestedPick<IStudent, ['address', 'lineOne']>) =>
  student.address.lineOne;

// 测试
declare const student: IStudent
const res = getAddressLineOne(student) // string

或者,你可以缩小getAddressLineOne函数的参数:

const getAddressLineOne2 = (address: Pick<IStudent["address"], "lineOne">) => address.lineOne;

代码示例

英文:

You can create your own NestedPick type:

type NestedPick&lt;T, K extends string[]&gt; = T extends object ? {
  [P in Extract&lt;keyof T, K[0]&gt;]: NestedPick&lt;T[P], Tail&lt;K&gt;&gt;
} : T

// get tail of tuple
type Tail&lt;T extends any[]&gt; = ((...args: T) =&gt; any) extends (head: any, ...tail: infer I) =&gt; any
  ? I : never

Haven't tested edge cases, but this might be a good starting point. Then getAddressLineOne looks like:

const getAddressLineOne = (student: NestedPick&lt;IStudent, [&#39;address&#39;, &#39;lineOne&#39;]&gt;) =&gt;
  student.address.lineOne;

// Test
declare const student: IStudent
const res = getAddressLineOne(student) // string

Alernatively, you could narrow getAddressLineOne function parameter:

const getAddressLineOne2 = (address: Pick&lt;IStudent[&quot;address&quot;], &quot;lineOne&quot;&gt;) =&gt; address.lineOne;

Code sample

huangapple
  • 本文由 发表于 2020年1月6日 17:54:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/59609924.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定