元素隐式具有 'any' 类型,因为类型没有索引签名

Element implicitly has 'any' type because type has no index signature

我正在尝试在 TypeScript 中实现类似 Maybe.withDefault 的东西:

const locale = 'en-US'; //navigator.language
const systemLanguage:Language = withDefault(locale, 'en');


const languages = {en: <'en'>'en', mk: <'mk'>'mk', es: <'es'>'es'};
type Language = keyof typeof languages;


const withDefault = (candidate: string, def: Language): Language =>
  languages[langCandidate] ? languages[langCandidate] : def;

虽然我理解 string 如何与 Language 发生冲突,但我想知道如何在不更改语言结构的情况下解决这个问题,这会给我带来紧凑的类型。

你可以通过引入一个可以被 Language 或字符串索引的中间类型,并引入一个将 languages 隐式转换为该类型的中间函数(转换成功而无需类型转换)来做到这一点因为这些类型是单向兼容的):

const languages = {en: <'en'>'en', mk: <'mk'>'mk', es: <'es'>'es'};
type Language = keyof typeof languages;


type LanguageLookup = {[n in Language | string]: Language};

function languageLookup(language: string, lookup: LanguageLookup): Language | undefined {
    return lookup[language];
}

const withDefault = (candidate: string, def: Language): Language =>
    languageLookup(candidate, languages) || def;