定义没有索引签名的打字稿对象形状

DaS*_*Sch 5 typescript

我真的很好奇这是否在 TypeScript 中存在某种设计差距。\n假设我有一个函数,它接受任何满足此接口的对象

\n
interface Params {\n    [key: string]: string | number | boolean | undefined | null;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

因此键必须是字符串,属性的类型可以是原始类型或 void。

\n

如果我现在指定一些采用特定接口的方法,该接口本身满足 Params 接口,我会收到错误,另一个接口没有索引签名。\n因此另一个接口可能看起来像这样。

\n
interface Foo {\n    bar: string;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我还尝试将签名更改为Record<string, string | number | boolean | undefined | null>,但这也给出了缺少索引签名错误。

\n

我的整个代码可能看起来像这样。给出一个完整的图片。所以我需要指定对象的键和值类型,以便能够在中执行某些操作Object.entries

\n
function specificFunction(obj: Foo) {\n  genericFunction(obj);\n}\n\nfunction genericFunction(params: Params) {\n  Object.entries(params).forEach(([key, value]) => {\n    \xe2\x80\xa6\n  })\n}\n
Run Code Online (Sandbox Code Playgroud)\n

编辑: \n重要说明,特定函数的行为应该保持不变,因为它应该用于缩小允许的接口,因为在这种特殊情况下,只允许具有某些属性的对象来确保特定的结果。

\n

cap*_*ian 5

genericFunction期望类型为index signature.

Foo默认情况下没有索引签名,因为它是一个接口。

但有一个小提示。如果你使用type关键字来声明Foo而不是interface- 它将起作用。

为什么?

因为type's 默认有索引签名。

这个答案。

因此,接下来的代码将编译:

interface Params {
    [key: string]: string | number | boolean | undefined | null;
}

// use type here instead of interface
type Foo = {
    bar: string;
}

function specificFunction(obj: Foo) {
  genericFunction(obj);
}

function genericFunction(params: Params) {
  Object.entries(params).forEach(([key, value]) => {

  })
}
Run Code Online (Sandbox Code Playgroud)

操场

更新 2 如果您无法控制ParamsFoo,您可以使用下一个实用程序类型:

interface Params {
    [key: string]: string | number | boolean | undefined | null;
}

interface Foo {
    bar: string;
}

type Values<T> = T[keyof T]

type MakeIndexed<T> = {
    [P in keyof T]: T[P]
}

function specificFunction(obj: MakeIndexed<Foo>) {
    genericFunction(obj);
}

function genericFunction(params: Params) {
    Object.entries(params).forEach(([key, value]) => {

    })
}
Run Code Online (Sandbox Code Playgroud)