繁体   English   中英

如何在 TypeScript 中键入函数参数来映射对象属性?

[英]How to type function parameters in TypeScript to map object properties?

我试图了解如何正确设置propvalue函数参数的类型(参见?? ),以便 prop 和 value 必须与MyStorage接口中定义的匹配。 设置keyof MyStorage应该足以正确输入prop ,但是我完全不知道如何输入value

interface MyStorage {
  prop1?: string;
  prop2?: number;
  prop3?: boolean;
  prop4?: Array<string>;
  prop5?: 'value1' | 'value2';
}

const myStorage: MyStorage = {};

const setProp = (prop: ??, value: ??) => {
  myStorage[prop] = value;
}

setProp('prop1', 'Ok');
setProp('prop1', 5); // Not Ok
setProp('prop5', 'value1'); // Ok
setProp('prop5', 'value5'); // Not Ok

最终目标是将此函数转换为这样的通用版本:

const genericSetProp = <T>(prop: ??, value: ??, storage: T) => {
  storage[prop] = value;
}

genericSetProp('prop1', 'Ok', myStorage);
genericSetProp('prop1', 5, myStorage); // Not Ok
genericSetProp('prop5', 'value1', myStorage); // Ok
genericSetProp('prop5', 'value5', myStorage); // Not Ok

如何设置这些类型以使 TypeScript 正确检查这些参数?

您可以通过执行MyStorage["prop1"]等操作来使用结构成员的类型。要获取"prop1"部分,您可以要求该keykeyof MyStorage 所以第一个版本看起来像这样:

const setProp = <K extends keyof MyStorage>(prop: K, value: MyStorage[K]) => {
    myStorage[prop] = value;
};

并且您确实可以通过使用第二个泛型类型参数从第三个参数推断出MyStorage类型来实现泛型:

const genericSetProp = <T, K extends keyof T>(prop: K, value: T[K], storage: T) => {
    storage[prop] = value;
};

游乐场链接

只需使用额外的通用:

interface MyStorage {
  prop1?: string;
  prop2?: number;
  prop3?: boolean;
  prop4?: Array<string>;
  prop5?: 'value1' | 'value2';
}

const myStorage: MyStorage = {};

const setProp = <Prop extends keyof MyStorage,>(prop: Prop, value: MyStorage[Prop]) => {
  myStorage[prop] = value;
}

setProp('prop1', 'Ok');
setProp('prop1', 5); // Not Ok
setProp('prop5', 'value1'); // Ok
setProp('prop5', 'value5'); // Not Ok

FP方法:

const withObject = <Obj,>(obj: Obj) => <Prop extends keyof MyStorage>(
  prop: Prop, value: MyStorage[Prop]
) => ({
  ...obj,
  [prop]: value
})

const setProp = withObject(myStorage)

setProp('prop1', 'Ok');
setProp('prop1', 5); // Not Ok
setProp('prop5', 'value1'); // Ok
setProp('prop5', 'value5'); // Not Ok

操场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM