typescript :类型恰好具有另一种类型的一个属性

标签 typescript

我有界面,想用这个界面的键来打字。

  • 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/

相关文章:

javascript - 如何比较日期时间字符串格式 : (YYYY-MM-DD XX:YY) in javascript

javascript - 为什么 styled-components 将我的属性添加到 DOM 中?

javascript - 点后仅保留两位小数( Angular )

angular - 如何将异步服务用于 Angular httpClient 拦截器

node.js - Node 类型在 typescript 中不起作用

angular - 将 TypeMoq Mock 与 Angular TestBed 结合使用

typescript - (<T>(x : any): x is T[] => x && typeof x. 长度 === 'number' )

javascript - 删除递归对象条目

reactjs - 如何在 react ts 中将 bool 值传递给 Material UI MenuItem 值?

javascript - TypeScript:在不显式定义键的情况下创建类型化记录