有没有一种方法可以从其属性推断出通用参数?

时间:2019-08-26 17:48:46

标签: typescript generics intellisense

我试图从另一个对象属性推断一个对象属性的类型。

type Dog = { name: string };
type Cat = { age: number};

class AnimalType<T> {

}

class AnimalTypeRegistry {
    static Dog: AnimalType<Dog>
    static Cat: AnimalType<Cat>
}

interface IConfig<T> {
    type: AnimalType<T>;
    init: Partial<T>;
}

class Config {
    get list(): IConfig<any>[] {
        return [
            {
                type: AnimalTypeRegistry.Dog,
                init: {
                    name: 'Bob' // Note - intellisense does not know this exists.
                }
            },
            {
                type: AnimalTypeRegistry.Cat,
                init: {
                    age: 3 // Note - intellisense does not know this exists.
                }
            }
        ]
    }
}

我希望intellisense能够将init推断为Dog类型,并且name属性存在。而是默认为任何(由于函数返回类型)。

1 个答案:

答案 0 :(得分:1)

如果您使用IConfig<any>,则会丢失所有类型提示,因为any可能是任何东西。

如果您希望对类型进行足够的区分以获取有意义的IntelliSense,则有助于固定union的这些类型...尤其是discriminated union

// Use a discriminated union for types
type Dog = { name: string; kind: "Dog" };
type Cat = { age: number; kind: "Cat" };
type Animal = Dog | Cat;

在这里,Animal是有区别的联合:discriminant属性称为kind,您可以使用字符串文字值"Dog""Cat"来区别你拥有工会。

暂时不在代码中使用“注册表”和“ AnimalType<T>”(如果以后需要,您可以自己获得此功能),我将IConfig<K>依赖于{{1所讨论的kind的}}属性K

Animal

请注意,// have IConfig<K> depend on the discriminant K interface IConfig<K extends Animal["kind"]> { type: K; init: Partial<Extract<Animal, { kind: K }>>; } 属性是initPartial<Extract<Animal, {kind: K}>>对您很有意义,但是Partial用于extract Extract<Animal, {kind: K}>属性为Animal的{​​{1}}联合的特定成员。 / p>


然后您要kind输出一个K元素的数组。您可以通过编程方式从list()生成该类型,如下所示:

IConfig<"Dog"> | IConfig<"Cat">

(我们使用mappedlookup类型来做到这一点)。

请注意,您不要Animal(联合位于另一个位置),因为这些将允许像// SomeConfig is the union of all possible IConfig<K> types type SomeConfig = { [K in Animal["kind"]]: IConfig<K> }[Animal["kind"]]; // type SomeConfig = IConfig<"Dog"> | IConfig<"Cat"> 这样的合并元素,我认为您不需要不想。


最后,您获得了想要的IntelliSense:

IConfig<"Dog" | "Cat">

好的,希望能有所帮助。祝你好运!

Link to code