首页 > 解决方案 > 如何在 TypeScript 中使用泛型索引记录?

问题描述

我有一个LocalizationMap并且我正在尝试使用泛型对其进行索引,下面是我的尝试,我在出现类型错误的地方添加了注释

interface Greeting {
  type: string;
  props: never;
}

interface NumbersSeven {
  type: number;
  props: never;
}

interface ExtrasArraysMixed {
  type: [string, number];
  props: ExtrasArraysMixedProps;
}

interface ExtrasArraysMixedProps {
  name: string;
}

interface City {
  type: string;
  props: CityProps;
}

interface CityProps {
  city: string;
}

interface LocalizationMap {
  greeting: Greeting;
  "numbers.seven": NumbersSeven;
  "extras.arrays.mixed": ExtrasArraysMixed;
  city: City;
}

const availableLanguages = ["en", "nl"] as const;

type Cache = Record<typeof availableLanguages[number], LocalizationMap>;

export const setLanguage = <T extends keyof Cache>(lang: T) => {
  // Type '"props"' cannot be used to index type 'K'.
  return <K extends keyof Cache[T], V = K["props"]>(
    key: K,
    ...placeholders: V extends never ? [] : [V]
  ): V => {
    let translation = key
      // Property 'split' does not exist on type 'K'.
      .split(".")
      .reduce((acc, val) => acc[val], cache[lang]);

    return translation;
  };
};

// Usage I am trying to get
const x = setLanguage("en");
// An argument for 'placeholders' was not provided.
x("greeting"); 
x("extras.arrays.mixed", { name: "Dan" });

标签: typescripttypescript-typings

解决方案


看来您正在索引错误的类型,并且可能想要这样的东西:

const availableLanguages = ["en", "nl"] as const;

type CacheKeys = typeof availableLanguages[number]
type Cache = Record<CacheKeys, LocalizationMap>;

export const setLanguage = <T extends CacheKeys>(lang: T) => {
    return <K extends keyof LocalizationMap, V extends LocalizationMap[K]['props']>
    (
        key: K,
        ...placeholders: V[]
    ): V => {
        return key.split(".").reduce((acc, val) => acc[val], cache[lang]);
    };
};

const x = setLanguage("en");
x("greeting");                             // works
x("extras.arrays.mixed", { name: "Dan" }); // works
x("city", { city: "Odessa" });             // works

推荐阅读