我有界面,想用这个界面的键来打字。
- key 可以是可选的
- key 必须在该界面中
例子
interface Test {
a: string;
b: string;
c: string;
d: string | undefined;
e: string | undefined;
}
我的新类型可以具有上述键中的一个属性。我像下面这样写
type MyNewType<T> = {
[key in keyof T]: T[key];
};
我将此类型用作 MyNewType<Test>
, 但遇到错误。
Type '{ a: string; }' is missing the following properties from type 'MyNewType': b, c, d, e.
如何选择性地使用属性?
澄清
我在 React 中使用 reducer 并调用 dispatch
接受 Action 创建者作为参数的函数。 Test
type 是状态类型并且 MyNewType<Test>
是有效负载类型。 Action creator 接受 payload,payload 可以变成 { a: 'a'}
, { b: 'b' }
, 或 { d: undefined }
.但是错误表明有效负载必须包含所有属性。
最佳答案
如果不需要通用解决方案,可以使用以下方法:
MyNewType = { a: string }
| { b: string }
| { c: string }
| { d: string | undefined }
| { d: string | undefined };
我想不出有什么方法可以为泛型 T
做这件事。
但您可以使用另一种方法:您可以为键和值使用单独的属性,而不是只选择单个键值对,例如:
{
key: "a",
value: "a"
}
这可以以通用方式完成:
type MyNewType<T> = {
key: keyof T;
value: T[keyof T];
}
但是,这不是很精确,因为您可以将任何键与任何值组合。
另一种方法是:
type MyNewType<T, K extends keyof T> = {
key: K;
value: T[K];
}
Wich 按预期工作,但引入了一个新的类型参数来表示键类型。 例如,您可以将其用作:
function dispatch<K extends keyof Test>(testPayload: MyNewType<Test, K>) {
// do something with payload
}
dispatch({ key: "a", value: "a" }); // OK
dispatch({ key: "a", value: undefined }); // Error, because Test.a cannot be undefined
dispatch({ key: "d", value: undefined }); // OK
dispatch({ key: "x", value: undefined }); // Error, because Test does not have property "x"
编辑
我还尝试了以下方法来完全按照要求创建类型:
type MyNewType<T, K extends keyof T> = {
[key: K]: T[K];
}
但是 TypeScript 在 key
上给出了以下错误:
An index signature parameter type must be either 'string' or 'number'.
关于 typescript :类型恰好具有另一种类型的一个属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62060188/