通过同级属性推断对象类型- Typescript

a0zr77ik  于 2023-01-18  发布在  TypeScript
关注(0)|答案(2)|浏览(163)

是否可以基于同一对象中的另一个属性Assert该对象的属性?
但是,如何根据type属性的值推断values的类型呢?

type StepKeys = "Test1" | "Test2";

interface objectMap {
    "Test1": {
        name: string
    },
    "Test2": {
        age: number
    }
};

interface Step<T extends StepKeys = StepKeys> {
    type: T;
    value: objectMap[T]
};

const steps: Record<string, Step> = {
    "Step1": {
        type: "Test1",
        value: {

        }
    }
}

这里values的类型是{ name: string; } | { age: number; }的并集。
有可能推断出它的可能值吗?
typescript

lb3vh1jj

lb3vh1jj1#

嗨,如果你想有效地区分这个联合,类型参数不应该是一个联合,而是寻求“推”联合一个类型。这是因为我们希望每个Step类型有它自己唯一的类型参数,而不是可能的类型参数的联合。所以一个小的变化,但完成你想要的。

const steps: Record<string, Step<'Test1'> | Step<'Test2'>> = {
    "Step1": {
        type: "Test1",
        value: {
            // infer ?
            age: 11,
// ^^^ correctly throws error 
// Object literal may only specify known properties, and 'age' does not exist in type '{ name: string; }'.(2322)
            name: 'test',
        }
    }
}

使用索引访问Map类型,如果有更多的键/值对,您可以自动创建一个有区别的并集。

type Steps = Record<string, {
    [key in StepKeys]: Step<key>
}[StepKeys]>

View on TS Playground

jw5wzhpr

jw5wzhpr2#

唯一能达到你想要的效果的方法不是很好,但它确实有效,问题是你必须手动输入每一个键(这使得它不可能通用或可伸缩)。

interface PeoplePropsMap {
    withName: {
        name: string
    },

    withAge: {
        age: number
    }
};

type People =
    { type: 'withName', value: PeoplePropsMap['withName'] } |
    { type: 'withAge',  value: PeoplePropsMap['withAge']  }

const steps: Record<string, People> = {
    john: {
        type: 'withAge',
        value: {
            age: 10  
        }
    }
}

相关问题