typescript Map类型函数getter

b4lqfgs4  于 2023-05-01  发布在  TypeScript
关注(0)|答案(1)|浏览(159)

我有这些类型:

type Device = {
  manufacturer: string;
  price: number;
  releaseYear: number;
};

type Accessory = {
  color: string;
  size: number;
};

我有formatter:

type Formatter<T> = {
  [Key in keyof T as `format${Capitalize<Key & string>}`]: (
    value: T[Key]
  ) => string;
};

我想创建一个函数,它通过泛型返回格式化类型。就像这样:

const getFormatted = <T>(obj: T): Formatter<T> {
  const newObj: Formatter<T> = {};
  Object.keys(obj).forEach((key) => {
      newObj[`format${capitalize(key)}`] = () => obj[key];
  })

  return newObj;
}

const { formatColor, formatSize } = getFormatted<Accessory>({
  color: "#fff",
  size: 2
})

但我有错误:

Element implicitly has an 'any' type because expression of type '`format${string}`' can't be used to index type 'Formatter '
uyhoqukh

uyhoqukh1#

TypeScript不知道newObj的键是否是Formatter类型的有效键。这是因为TypeScript无法推断出[Key in keyof T as format${Capitalize〈Key & string〉}]中模板文字所创建的确切键。
要解决此问题,可以在将键添加到newObj时在键上添加类型Assert,这会告诉TypeScript您正在使用的动态键与Formatter中定义的键类型匹配

type Device = {
  manufacturer: string;
  price: number;
  releaseYear: number;
};

type Accessory = {
  color: string;
  size: number;
};

type Formatter<T> = {
  [Key in keyof T as `format${Capitalize<Extract<Key, string>>}`]: (
    value: T[Extract<Key, keyof T>]
  ) => string;
};

interface MyObject {
  [key: string]: string | number | boolean;
}

function getFormatted<T extends MyObject>(obj: T): Formatter<T> {
  const newObj: Formatter<T> = {} as Formatter<T>;
  
  Object.keys(obj).forEach((key) => {
    const formattedKey = `format${capitalize(key)}` as keyof Formatter<T>;
        newObj[formattedKey] = (value: T[keyof T]): string => `${value}`;
  });

  return newObj;
}

const { formatColor, formatSize } = getFormatted<Accessory>({
  color: "#fff",
  size: 2
})

function capitalize(str: string): string {
  return str.charAt(0).toUpperCase() + str.slice(1);
}

相关问题