将数字转换为字符串而不扩展类型

时间:2019-03-29 23:42:53

标签: typescript react-native

我使用的是本机响应,文本上的fontWeight样式值接受以下内容:

fontWeight?: "normal" | "bold" | "100" | "200" | "300" | "400" | "500" | "600" | "700" | "800" | "900";

我有一个第三方API,该API返回fontWeight作为数字。该API将为fontWeight返回以下内容:

100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900

我正在尝试将两者联系起来,但似乎无法弄清楚。做

fontWeight: APIResult.fontWeight.toString(),引发了错误,因为那时React native需要一个准确的值时,我正在传递string

2 个答案:

答案 0 :(得分:0)

您是否考虑过将一种格式解析为另一种格式?看起来像这样:

type S = "normal" | "bold" | "100" | "200" | "300" | "400" | "500" | "600" | "700" | "800" | "900";
type N = 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;

type ParseFontWeightToString<T extends N> =
  T extends 100 ? '100' :
  T extends 200 ? '200' :
  T extends 300 ? '300' :
  T extends 400 ? '400' :
  T extends 500 ? '500' :
  T extends 600 ? '600' :
  T extends 700 ? '700' :
  T extends 800 ? '800' :
  T extends 900 ? '900' :
  never

type R = ParseFontWeightToString<700> // "700"
type R1 = ParseFontWeightToString<750> // ERROR

这不是精美的代码悬停工具,您只需声明一次即可。

Playground

答案 1 :(得分:0)

最简单的(但不是类型安全的)解决方案只是使用type assertion

type FontWeightAPIString = "100" | "200" | "300" | "400" | "500" |
  "600" | "700" | "800" | "900";

{ fontWeight: APIResult.fontWeight.toString() as FontWeightAPIString } 

或更简单(但更不安全)

{ fontWeight: APIResult.fontWeight.toString() as any } 

另一种可能的解决方案,如果您想尝试帮助编译器理解调用toString()的含义:

interface WeightMap {
    100: "100";
    200: "200";
    300: "300";
    400: "400";
    500: "500";
    600: "600";
    700: "700";
    800: "800";
    900: "900";
}
type WeightNumber<N extends keyof WeightMap = keyof WeightMap> = 
  { toString(this: number): WeightMap[N] } & N;

interface APIResult {
    fontWeight: WeightNumber; // was originally just 100 | 200 | ... | 800 | 900 ?
}

interface MyStyle {
    fontWeight?: "normal" | "bold" | "100" | "200" | "300" | "400" | 
      "500" | "600" | "700" | "800" | "900";
}

declare const apiResult: APIResult;
const foo: MyStyle = {
    fontWeight: apiResult.fontWeight.toString() // no error now
}

在这里,我们将数字权重到字符串权重的映射表示为WeightMap,并具有一个名为WeightNumber的新类型别名,它是number的子类型。已知WeightNumber是数字文字的相关联合(100 | 200 | ... | 800 | 900),它有一个显式toString()方法,该方法返回字符串文字的相关联合("100" | "200" | ... | "800" | "900") 。如果需要,您还可以获取更具体的类型,例如WeightNumber<200>

然后,我们声明APIResult['fontWeight']WeightNumber

这使编译器可以推断出APIResult['fontWeight']['toString']的返回类型符合fontWeight样式,并且您没有错误。


好的,希望能有所帮助。祝你好运!