首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >动态规划类型

动态规划类型
EN

Stack Overflow用户
提问于 2019-01-31 18:43:04
回答 1查看 194关注 0票数 1
代码语言:javascript
复制
type someObj = {
    a: number,
    b: Array<string>,
    c: { d: string },
    e: {
        f: string,
        g: Array<{
            h: string,
            i: Array<number>
        }>
    },
    j: {
        k: string,
        l: Array<string>
    },
    m: Array<Array<string>>
};

type someGeneric<T /* can be primitive, array or object */> = ???;
// Expected Result


type someObjGenericResult = {
    b: (item: string) => void,
    e: {
        g: (item: { h: string, i: Array<number> }) => {
            i: (item: number) => void
        }
    },
    j: { l: (item: string) => void },
    m: (item: Array<string>) => (item: string) => void 
};

因此,我希望编写一个泛型,它将接受任意值,并在对象中的每个数组上执行一个函数(不管它是如何嵌套的),并具有以下属性

=>排除所有原语(比如某个Obj.a)

=>排除没有将数组作为类型的支柱的对象(例如

=>,但是包含一个对象,它有一个数组作为支柱(比如omeObj.j)。

=>用户竞相寻找具有嵌套数组的数组(比如一些Obj.m)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-01 02:23:09

因问题更改而更新

如果您只是研究如何进行类型输入(而不是将someObj实例转换为someObjGenericResult实例的运行时代码),我认为以下内容将有效:

代码语言:javascript
复制
// HasNestedArrays<T> outputs unknown (meaning true) or never (meaning false)
// depending on whether T is an array or an object with at least one
// property that HasNestedArrays itself.  This is a recursive definition.
// HasNestedArrays<{a: {b: {c: string[]}}}> should return unknown,
// HasNestedArrays<{a: {b: {c: string}}}> should return never.
type HasNestedArrays<T> = T extends Array<any> ? unknown :
  T extends object ? { [K in keyof T]: HasNestedArrays<T[K]> }[keyof T] : never;

// PickHasNestedArrays<T> takes an object type T and removes any properties
// that do not pass the HasNestedArrays test. 
// PickHasNestedArrays<{a: string, b: string[], c: {d: string[]}}> should return
// {b: string[], c: {d: string[]}}.
type PickHasNestedArrays<T extends object> = Pick<T,
  { [K in keyof T]: unknown extends HasNestedArrays<T[K]> ? K : never }[keyof T]
>

// SomeGeneric<T> is the type you want: 
// If T is an array like U[], return a function (item: U) => SomeGeneric<U>.
// If T is an object, strip all the non-array-containing properties out
// (via PickHasNestedArrays<T>) and assign the stripped object to V.
// If V is an empty object, then return void. 
// Otherwise, return a new object whose properties have the same keys K from V
// but whose values are SomeGeneric<V[K]>.
type SomeGeneric<T> = T extends Array<infer U> ?
  (item: U) => SomeGeneric<U> :
  T extends object ? (
    PickHasNestedArrays<T> extends infer V ? (
      {} extends V ? void : { [K in keyof V]: SomeGeneric<V[K]> }
    ) : never
  ) : void;

type someObjGenericResult = SomeGeneric<someObj>;

注意,在TypeScript中,unknown是所谓的顶型,它包含所有的值.这基本上是类型的“真实”。never就是所谓的底式,它不包含任何值.这基本上是类型的“假”。当我执行类似布尔型的类型操作时,我倾向于输出unknown/never用于true/false,因为它有时会使后续操作更容易。

HasNestedArrays<T>PickHasNestedArrays<T>类型用于去掉您不关心的T的所有属性。SomeGeneric<T>是您所要求的类型函数。我已经在上面的注释中解释了它们所做的事情,但是它们的工作方式需要理解条件类型映射类型查找类型。如果您了解所有的表示法,并需要更多关于在某些情况下正在发生的事情的细节,我可以详细说明。

我不确定SomeGeneric<T>是否是您真正想要的,因为有一些边缘情况,如SomeGeneric<number>SomeGeneric<{a: number}>等等。我非常肯定,上面的定义为大多数边缘情况下的void

不管怎么说,我希望这能帮上忙。祝好运!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54467264

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档