#typescript #react-native
#typescript #react-native
Вопрос:
Я использую react native, и fontWeight
значение стиля в тексте принимает следующее:
fontWeight?: "normal" | "bold" | "100" | "200" | "300" | "400" | "500" | "600" | "700" | "800" | "900";
У меня есть сторонний API, который возвращает FontWeight в виде числа. Этот API вернет следующее для FontWeight:
100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
Я пытаюсь соединить эти два, но, похоже, не могу в этом разобраться. Выполнение
fontWeight: APIResult.fontWeight.toString(),
выдает ошибку, поскольку в этот момент я передаю string
, когда react native ожидает точное значение.
Комментарии:
1. Вы уверены, что это
APIResult.fontWeight.toString()
будет одним из"normal" | "bold" | "100" | "200" | "300" | "400" | "500" | "600" | "700" | "800" | "900"
? Или возможно, что этого не будет?2. Я отредактировал свой вопрос, API возвращает
100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
3. Не могли бы вы вставить трассировку стека?
Ответ №1:
Вы думали о синтаксическом анализе из одного формата в другой? Это будет выглядеть следующим образом:
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
Это не красивый code hoverer, вы будете объявлять его только один раз.
<a rel="noreferrer noopener nofollow" href="https://www.typescriptlang.org/play/index.html#src=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 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»» rel=»nofollow noreferrer»>Игровая площадка
Ответ №2:
Самое простое (но не типобезопасное) решение — просто использовать утверждение типа
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] } amp; 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
Известно, что A является соответствующим объединением числовых литералов ( 100 | 200 | ... | 800 | 900
), и у него есть явный toString()
метод, который возвращает соответствующее объединение строковых литералов ( "100" | "200" | ... | "800" | "900"
). Вы также можете получить более конкретный тип, такой как WeightNumber<200>
, если хотите.
Затем мы объявляем, что APIResult['fontWeight']
это WeightNumber
.
Это позволяет компилятору сделать вывод, что возвращаемый тип APIResult['fontWeight']['toString']
соответствует fontWeight
стилю и у вас нет ошибок.
Хорошо, надеюсь, это поможет. Удачи!