Typescript:仅具有另一类型的一个属性的类型

Typescript:仅具有另一类型的一个属性的类型,typescript,Typescript,我有一个接口,我想用这个接口的键来创建类型 密钥可以是可选的 密钥必须在该接口中 范例 接口测试{ a:弦; b:弦; c:字符串; d:字符串|未定义; e:字符串|未定义; } 我的新类型可以具有上述键中的一个属性。我像下面这样写 类型MyNewType={ [key in keyof T]:T[key]; }; 我将此类型用作MyNewType,但遇到错误 类型“{a:string;}”缺少类型“MyNewType”中的以下属性:b、c、d、e。 如何选择使用属性 澄清 我在Rea

我有一个接口,我想用这个接口的键来创建类型

  • 密钥可以是可选的
  • 密钥必须在该接口中
范例

接口测试{
a:弦;
b:弦;
c:字符串;
d:字符串|未定义;
e:字符串|未定义;
}
我的新类型可以具有上述键中的一个属性。我像下面这样写

类型MyNewType={
[key in keyof T]:T[key];
};
我将此类型用作
MyNewType
,但遇到错误

类型“{a:string;}”缺少类型“MyNewType”中的以下属性:b、c、d、e。

如何选择使用属性

澄清


我在React中使用reducer并调用
dispatch
函数,该函数接受action creater作为参数<代码>测试类型为状态类型,
MyNewType
为有效负载类型。Action creator接受有效负载,有效负载可以变成
{a:'a'}
{b:'b'}
,或
{d:undefined}
。但是,错误表明有效负载必须包含所有属性。

在可选键后面添加一个

例如,如果要使a&b成为可选的

interface Test {
  a?: string;
  b?: string;
  c: string;
  d: string | undefined;
  e: string | 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];
}
类型MyNewType={
密钥:keyoft;
值:T[keyof T];
}
但是,这不是很精确,因为您可以将任何键与任何值组合

另一种办法是:

type MyNewType<T, K extends keyof T> = {
  key: K;
  value: T[K];
}
类型MyNewType={
关键词:K;
值: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"
函数分派(testPayload:MyNewType){
//用有效载荷做点什么
}
分派({键:“a”,值:“a”});//好啊
分派({key:a',value:undefined});//错误,因为无法取消定义Test.a
分派({键:“d”,值:未定义});//好啊
分派({键:“x”,值:未定义});//错误,因为测试没有属性“x”
编辑

我还尝试了以下方法来完全按照请求创建类型:

type MyNewType<T, K extends keyof T> = {
  [key: K]: T[K];
}
类型MyNewType={
[键:K]:T[K];
}
但是TypeScript在
键上给出了以下错误:

索引签名参数类型必须为“字符串”或“数字”


我有一个类似的问题,并提出了以下设计

定义一个接口或类型,该接口或类型包含您想要支持的每个属性,但使它们都是可选的,并且永远不使用类型。您可以使用这些属性中的任何一个,但不能为它们分配任何内容

接口基类型{
答:从来没有;
b:从来没有;
c:从不;
d:从来没有;
e:从来没有;
}
通过省略base never属性并将其替换为所需的类型,为每个属性创建一个类型,但现在它不再是可选的

typeatype=Omit&{“a”:string};
类型BType=省略&{“b”:字符串};
类型CType=省略&{“c”:字符串};
类型DType=省略&{“d”:字符串|未定义};
类型EType=省略&{“e”:字符串|未定义};
组合所有这些单一属性类型以创建您的
MyNewType
。此类型的任何实例都必须是上述单个类型之一

type MyNewType=AType | BType | CType | DType | EType;
以下行编译或触发类型脚本错误:

让testA:MyNewType={“a”:“test”}//a存在,并且是一个字符串
设testB:MyNewType={“b”:1}//b存在,但不能是数字
设testD:MyNewType={“d”:未定义}//d存在,并且可能未定义
让testMultiple:MyNewType={“a”:“某个字符串”,“b”:“另一个字符串”}//不能包含多个属性

我也在中设置了该属性,因此您可以实时查看TypeScript错误。

“上述键中的一个属性”-这实际上意味着什么?我在将参数传递给函数时只使用一个属性,参数的类型是
MyNewType
。您仍然需要更好地澄清您的请求:您想要一个只有一个(没有其他内容)的类型吗原物的财产;或者至少一个?或者其他什么?也许你也应该编辑问题标题——“选择性地使用属性”会让所有人认为你在搜索@Lim Jing-Rong提供的答案。@mperk的反馈很好,但我的英语不好。你能推荐一个吗?
a
b
不能是
未定义的
,“可选”的意思是传递给函数的参数只能是一个属性