接口或类型,其中一个字段的类型取决于另一个字段的类型

问题描述 投票:0回答:1

我已经有类似的问题:根据另一个字段的值声明一个字段的类型

主要区别是现在我不知道可能值的列表

所以假设我有这些接口:

interface One {
    children: Child[]
}

interface Child<T = any> {
    props: T,
    component: (props: T) => null
}

const ComponentOne = (props: string) => null;
const ComponentTwo = (props: number) => null;

const one: One = {
    children: [
        {
            props: 5,
            component: ComponentOne
        },
        {
            props: 'string',
            component: ComponentTwo
        }
    ]
}

我需要

props
component
的道具具有完全相同的类型。

上面的代码不会因为

any
而给出任何错误,但如果我删除它,
interface One
将会中断,因为它需要
Child
的类型,但它们不能都相同

这可能是一个非常明显的问题,但我不知道如何解决它

附注我没有任何理由地写了

interface
,如果可以使用
type
修复那么对我来说是可以接受的

typescript types
1个回答
0
投票

你应该付出一些努力来建立自己的类型。例如,您可以使用:

interface One<T> {
    children: (T extends any ? Child<T> : never)[]
}

props
类型分配给不同的子对象(您可以删除 Simplify 实用程序和内联
ONE
,这是为了调试和演示而完成的):

游乐场

type Simplify<T> = {[K in keyof T]: T[K] extends Function ? T[K] extends (...args: infer B) => infer A ? (...args: B) => Simplify<A> : never : Simplify<T[K]>} extends infer A ? A : never;

const ComponentOne = (props: string) => null;
const ComponentTwo = (props: number) => null;
const Components = [ComponentOne, ComponentTwo];

{

interface One<T> {
    children: (T extends any ? Child<T> : never)[]
}

interface Child<T> {
    props: T,
    component: (props: T) => null
}

type ONE = Simplify<One<Parameters<typeof Components[number]>[0]>>;

const one: ONE = {
    children: [
        {
            props: '',
            component: ComponentOne
        },
        {
            props: 1,
            component: ComponentTwo
        }
    ]
}
}
// ==================== alternative ===================
{

interface Child<C extends (props: any) => null> {
    props: Parameters<C>[0],
    component: C
}

interface One<C extends (props: any) => null> {
    children: (C extends any ? Child<C> : never)[]
}


type ONE = Simplify<One<typeof Components[number]>>;

const one: ONE = {
    children: [
        {
            props: '',
            component: ComponentOne
        },
        {
            props: 1,
            component: ComponentTwo
        }
    ]
}
}
© www.soinside.com 2019 - 2024. All rights reserved.