打字稿:对象键的联合类型不能用作此对象的键

Zen*_*rko 4 typescript

我有一个用一个参数调用的函数。这个参数是对象。这个函数正在返回另一个对象,其中一个属性是传递给函数对象的值。当我尝试使用 obj[key] 表示法检索对象的值时遇到问题。

我确实理解,该密钥必须是正确的类型才能像这样使用。我不能使用简单的键作为字符串,如果在界面中我没有 [key: string]: any。但这不是问题。我的键是作为传递对象键的字符串的并集:'user' | “姓名”等

interface Twitter<T> {
  name: T;
  user: T;
  sex: T extends string ? boolean : string;
}
interface Facebook<T> {
  appName: T;
  whatever: T;
  imjustanexapmle: T;
}

type TwFbObjKeys = keyof Twitter<string> | keyof Facebook<string>
Run Code Online (Sandbox Code Playgroud)

我的函数如下所示:

public static getArrayOfObjects(
        queryParameters: Twitter<string> | Facebook<string>,
    ) {
        const keys = Object.keys(queryParameters) as TwFbObjKeys[];
        return keys.map((paramId) => ({
            paramId,
            value: queryParameters[paramId],
        }));
    }
Run Code Online (Sandbox Code Playgroud)

我希望,使用 paramId 类型为:'name' | '性' | '应用程序名称' | ...作为具有此键的对象的键,不会引发错误。但不幸的是我有错误:

TS7053:元素隐式具有“任何”类型,因为“名称”类型的表达式 | '性' | '应用程序名称' | ... 不能用于索引类型 Twitter | Facebook。类型 Twitter 上不存在属性“名称”| Facebook

我现在和它战斗了几个小时。知道我该如何解决吗?

for*_*d04 7

最好将函数参数定义queryParametersT具有约束的泛型类型<T extends Twitter<string> | Facebook<string>>而不是联合类型Twitter<string> | Facebook<string>

function getArrayOfObjects<T extends Twitter<string> | Facebook<string>>(
    queryParameters: T
) {
    const keys = Object.keys(queryParameters) as (keyof T)[];
    return keys.map((paramId) => ({
        paramId,
        value: queryParameters[paramId],
    }));
}
Run Code Online (Sandbox Code Playgroud)

操场

说明

通过使用泛型,您可以保留传入参数的类型,queryParameters并确保它将是Twitter<string> | Facebook<string>. paramId带类型keyof T现在可以访问queryParameters属性。

使用联合类型Twitter<string> | Facebook<string>,queryParameters将保持未确定状态,可以静止Twitter<string>Facebook<string>在函数体中。keyof在您的情况下,这会导致运算符和属性访问出现问题,因为您只能访问给定联合类型的所有成分的公共属性键。还有是没有共同的性质Twitter<string>Facebook<string>

为了更详细地说明这个问题,您可能打算定义TwFbObjKeys

// "name" | "user" | "sex" | "appName" | "whatever" | "imjustanexapmle"
type TwFbObjKeys = keyof Twitter<string> | keyof Facebook<string>

// not this: keyof only applies to Twitter<string> here: "name" | "user" | "sex" | Facebook<string>
type TwFbObjKeys_not = keyof Twitter<string> | Facebook<string>
Run Code Online (Sandbox Code Playgroud)

但这并不能单独解决问题。例子:

declare const queryParameters: Twitter<string> | Facebook<string>

// type keysOfQueryParameters = never
type keysOfQueryParameters = keyof typeof queryParameters

// ok, let's try to define all union keys manually
type TwFbObjKeys = "name" | "user" | "sex" | "appName" | "whatever" | "imjustanexapmle"
declare const unionKeys: TwFbObjKeys

// error: doesn't work either
queryParameters[unionKeys]

// this would work, if both Twitter and Facebook have "common" prop
queryParameters["common"]
Run Code Online (Sandbox Code Playgroud)

操场

借助泛型类型,我们可以keyof T安全地访问传入的queryParameters键。

  • 谢谢你!缺少 keyof 是我在此处“复制”代码时的一个拼写错误,但它仍然不起作用(正如您解释的那样)。当我提出您的改进后,错误不再存在。感谢您的健康回答。不仅是解决方案,而且是真正的答案。我不仅拥有没有错误的代码,而且还学到了一些新东西。对此,我真的非常感激。 (2认同)