【问题标题】:Property type depending on type of other property物业类型取决于其他物业的类型
【发布时间】:2020-12-12 13:32:04
【问题描述】:

所以我正在测试 TypeScript 我能走多远,但似乎无法解决以下问题。 当属性 A 具有一定价值时,如何限制属性 B 的类型?

// The type I want to declare
type Bar<T> = {
    prop: keyof T; // Select a property of the type
    value: T[keyof T]; // Provide the value of that property, this currently does not work
}

// Some random interface
interface Foo {
    id: number;
    name: string;
}

let bar: Bar<Foo> = {
    prop: "name", // Selected Foo.name: string
    value: 9,     // Should only allow strings
};

在这种情况下value 的属性类型是number | string,但我想强制它为字符串,因为选定的属性name 的类型是string


备注

我可以这样声明它,但界面不那么吸引人、清晰且更容易出错:只有一个属性应该是可选的,而且由于属性名称不存在,您并不真正知道预期的内容。或者我需要进一步嵌套对象。

type Bar<T> = {
    prop: {
        [K in keyof T]?: T[K];
    }
}

let bar: Bar<Foo> = {
    prop: {
        name: 'yay', // string is forced now
    }
};

【问题讨论】:

    标签: typescript types


    【解决方案1】:

    这是因为 Foo 有两个键,一个是字符串类型,另一个是数字。因此值是字符串 |数字。也许这行得通?

    // The type I want to declare
    type Bar<T, U> = {
        prop: keyof T; // Select a property of the type
        value: U; // Provide the value of that property, this currently does not work
    }
    
    // Some random interface
    interface Foo {
        id: number;
        name: string;
    }
    
    let bar: Bar<Foo, Foo['name']> = {
        prop: "name", // Selected Foo.name: string
        value: '9',     // Should only allow strings
    };
    

    【讨论】:

    • 是的,我想过类似的事情,但 Foo['name'] 在编译时还不知道。另外,现在name 被复制了,这也不是我真正想要的。
    【解决方案2】:

    根据您的使用示例:

    let bar: Bar<Foo> = {
        prop: "name", // Selected Foo.name: string
        value: 9,     // Should only allow strings
    };
    

    编译器无法推断出我们想要name 属性。它需要另一个类型参数,如Pick 实用程序类型。

    type PickEntry<T, K extends keyof T> = {
        prop: K; // Select a property of the type
        value: T[K]; // Provide the value of that property, this currently does not work
    }
    

    注意:PickEntryFoo 更明确

    然后,我们可以检测无效值类型:

    let nameEntry: PickEntry<Foo, 'name'> = {
        prop: "name",
        value: 9,
    //  ~~~~~ Error: Type 'number' is not assignable to type 'string'.(2322)
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-21
      • 1970-01-01
      • 2012-02-08
      • 1970-01-01
      • 2022-10-14
      • 1970-01-01
      • 1970-01-01
      • 2021-11-10
      相关资源
      最近更新 更多