在打字稿中声明对象类型

时间:2019-11-27 09:48:14

标签: typescript

需要声明一个对象类型。得到下面提到的错误:

let array = ["£179.95", "£199.95", "£89.95"]
let sum = array.compactMap { Double($0.replacingOccurrences(of: "£", with: "")) }
               .reduce(0.0, { $0 + $1 })
print(sum) // 469.84999999999997

TypeScript抛出以下错误:

  

类型'{[x:字符串]:{颜色:字符串}}'缺少类型'记录'中的以下属性:奔驰,奔驰轿车,奔驰车舱盖

3 个答案:

答案 0 :(得分:3)

您的代码有错误,KEY_MAP中的值实际上与CarKeys中指定的值不匹配。另外,carType中的分号必须是逗号。

要解决当前的问题,可以使用as const。在您的代码中,KEY_MAP的解析类型为:

const KEY_MAP: {
    mercedes: string;
    mercedes_sedan: string;
    mercedes_hatch: string;
}

像这样指定它:

const KEY_MAP = {
    mercedes: 'mercedes',
    mercedes_sedan: 'mercedes_sedan',
    mercedes_hatch: 'mercedes_hatch'
} as const;

然后解析的类型将是:

const KEY_MAP: {
    readonly mercedes: "mercedes";
    readonly mercedes_sedan: "mercedes_sedan";
    readonly mercedes_hatch: "mercedes_hatch";
}

应该编译哪个。

答案 1 :(得分:3)

两件事,首先是您写了type CarKeys = "mercedes" | "mercedes_sedan" | "mercedes_hatch",都带有下划线,但是KEY_MAP中的值带有连字符,这可能与您想匹配的不匹配解决。

第二,默认情况下,TS会推断typeof KEY_MAP{ mercedes: string; ... }而不是{ mercedes: "mercedes", ... }

这意味着typeof [KEY_MAP.mercedes]实际上是string,而不是"mercedes"字符串文字,因此typeof carType实际上是{ [key: string]: Car },这就是错误的原因。

要解决此问题,您可以在as const的末尾添加KEY_MAP

const KEY_MAP = {
  mercedes: 'mercedes',
  mercedes_sedan: 'mercedes-sedan',
  mercedes_hatch: 'mercedes-hatch'
} as const;

或者,您也可以将其变成enum

enum KEY_MAP {
  mercedes = 'mercedes',
  mercedes_sedan = 'mercedes-sedan',
  mercedes_hatch ='mercedes-hatch'
}

答案 2 :(得分:2)

首先,在使用TypeScript时,不需要使用Key-> Value map + String文字类型。您可以选择两者之一,因为这样可以确保类型安全。同样,使用Enum代替标准JS对象的方法会更合适,因为它可以解决以及一种语言构造中的值和类型。考虑仅使用Enum的解决方案:

interface Car { color: string; } 

enum KEY_MAP {
    mercedes = 'mercedes',
    mercedes_sedan = 'mercedes_sedan',
    mercedes_hatch = 'mercedes_hatch'
}

const carType: Record<KEY_MAP, Car> = {
    [KEY_MAP.mercedes]:{ color: 'red'},
    [KEY_MAP.mercedes_sedan]: {color: 'yellow'},
    [KEY_MAP.mercedes_hatch]: {color: 'black'}
}

也只有字符串文字的解决方案是完全有效的,并且类型安全。考虑:

type CarKeys = "mercedes" | "mercedes_sedan" | "mercedes_hatch";

interface Car { color: string; } 

const carType: Record<CarKeys, Car> = {
    mercedes:{ color: 'red'},
    mercedes_sedan: {color: 'yellow'},
    mercedes_hatch: {color: 'black'}
} // carType cannot be created with wrong key or value type

字符串文字类型不应被视为“魔术字符串”,因为编译器会监视它,并键入safe。我们不需要创建一些中间结构即可直接使用它。

最后一点同样重要。您可以通过为KEY_MAP指定正确的类型来直接修复实现。

type CarKeys = "mercedes" | "mercedes_sedan" | "mercedes_hatch";

interface Car { color: string; } 

const KEY_MAP: { [P in CarKeys]: P } = { mercedes: 'mercedes', mercedes_sedan: 'mercedes_sedan', mercedes_hatch: 'mercedes_hatch'};

const carType:Record<CarKeys, Car> = {
    [KEY_MAP.mercedes]:{ color: 'red'},
    [KEY_MAP.mercedes_sedan]: {color: 'yellow'},
    [KEY_MAP.mercedes_hatch]: {color: 'black'}
}; // no issues

核心是{ [P in CarKeys]: P }。我们说的是,我们的对象具有CarKeys中的确切单个项目作为键和值。