首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >类型记录:类型与另一种类型的属性完全相同

类型记录:类型与另一种类型的属性完全相同
EN

Stack Overflow用户
提问于 2020-05-28 08:26:22
回答 5查看 3.9K关注 0票数 3

我有接口,想用这个接口的键来打字。

  • 键可以是可选的
  • 键必须在该接口中。

示例

代码语言:javascript
运行
复制
interface Test {
  a: string;
  b: string;
  c: string;
  d: string | undefined;
  e: string | undefined;
}

我的新类型可以在上面的键中有一个属性。我的写作方式如下

代码语言:javascript
运行
复制
type MyNewType<T> = {
  [key in keyof T]: T[key];
};

我使用这种类型作为MyNewType<Test>,但是遇到了错误。

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

如何可选地使用属性?

Clarification

我在React中使用减缩器,并调用dispatch函数,它接受动作创建者作为参数。Test类型是状态类型,MyNewType<Test>类型是有效负载类型。操作创建者接受有效负载,并且有效负载可以变成{ a: 'a'}{ b: 'b' }{ d: undefined }。但是,error说,有效载荷必须包含所有属性。

EN

回答 5

Stack Overflow用户

发布于 2020-05-28 09:50:46

如果不需要通用解决方案,可以使用以下方法:

代码语言:javascript
运行
复制
MyNewType = { a: string }
          | { b: string }
          | { c: string }
          | { d: string | undefined }
          | { d: string | undefined };

对于泛型类型的T,我想不出有任何方法可以做到这一点。

但是您可以使用另一种方法:而不是仅仅选择一个键值对,您可以为键和值使用单独的属性,例如:

代码语言:javascript
运行
复制
{
  key: "a",
  value: "a"
}

这可以以一种通用的方式进行:

代码语言:javascript
运行
复制
type MyNewType<T> = {
  key: keyof T;
  value: T[keyof T];
}

但是,这并不是非常精确,因为您可以将任何键与任何值组合起来。

另一种办法是:

代码语言:javascript
运行
复制
type MyNewType<T, K extends keyof T> = {
  key: K;
  value: T[K];
}

Wich按预期工作,但引入一个新的类型参数来表示键类型。例如,您可以将它用作:

代码语言:javascript
运行
复制
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"

编辑

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

代码语言:javascript
运行
复制
type MyNewType<T, K extends keyof T> = {
  [key: K]: T[K];
}

但是TypeScript在key上给出了以下错误

索引签名参数类型必须为“string”或“number”。

票数 4
EN

Stack Overflow用户

发布于 2020-05-28 08:32:29

在可选键后面添加一个?

例如,如果您想使a&b可选

代码语言:javascript
运行
复制
interface Test {
  a?: string;
  b?: string;
  c: string;
  d: string | undefined;
  e: string | undefined;
}

参考资料:https://www.typescriptlang.org/docs/handbook/interfaces.html#optional-properties

票数 1
EN

Stack Overflow用户

发布于 2021-02-13 00:59:05

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

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

代码语言:javascript
运行
复制
interface BaseType {
  a?: never;
  b?: never;
  c?: never;
  d?: never;
  e?: never;
}

为每个属性创建一个类型,方法是省略base属性并用您想要的类型替换它,但是现在它不再是可选的了。

代码语言:javascript
运行
复制
type AType = Omit<BaseType, "a"> & { "a": string };
type BType = Omit<BaseType, "b"> & { "b": string };
type CType = Omit<BaseType, "c"> & { "c": string };
type DType = Omit<BaseType, "d"> & { "d": string | undefined };
type EType = Omit<BaseType, "e"> & { "e": string | undefined };

结合所有这些单一属性类型来创建MyNewType。此类型的任何实例都必须是上述单个类型之一。

代码语言:javascript
运行
复制
type MyNewType = AType | BType | CType | DType | EType;

以下几行编译或触发TypeScript错误:

代码语言:javascript
运行
复制
let testA : MyNewType = { "a": "test" } // A is present, and is a string
let testB : MyNewType = { "b": 1 } // B is present, but cannot be a number 
let testD : MyNewType = { "d": undefined } // D is present, and may be undefined 
let testMultiple : MyNewType = { "a": "Some String", "b": "Another String" } // Cannot include multiple properties

我还在游乐场中设置了这个选项,这样您就可以看到TypeScript错误了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62060188

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档