首页 文章

如何表达“用T作为参数|的函数字符串,它是TypeScript中T“的键

提问于
浏览
1

我有以下TypeScript,它可以工作:

interface Columns {
  [s: string]: string | ((item: any) => string);
}

const exportAsCsv = function (data: any[], columns: Columns): void {
  const header = Object.keys(columns)
    .map(x => `"${x}"`)
    .join(";");

  const rows = [];
  for (const item of data) {
    const row = Object
      .values(columns)
      .map(field => typeof field === 'function' ? field(item) : item[field])
      .map(x => (x || '').replace(/"/, '""'))
      .map(x => `"${x}"`)
      .join(";");
    rows.push(row);
  }
  console.log([header, ...rows].join("\r\n"));
}

我们的想法是传入一个对象数组,一个列对象,其中键是 Headers (可以是任何字符串),值应该是属性的名称或返回值的函数 .

const users = [{id: 1, name: 'Alice', isCool: true}, ...];
const columns = {
  'Id': 'id, 
  'Name': 'name', 
  'Is cool': u => u.isCool ? 'Yes' : 'No',
};
exportToCsv(users, columns);

这一切都有效,但我想知道如何一般地编写 Columns 类型 . 继续获取不可分配的东西,输入声明但未使用的参数等,等等 .

interface Columns<T> {
  [s: string]: ?;
}
const exportAsCsv = function <T> (data: T[], columns: Columns<T>): void

我该如何正确表达?

1 回答

  • 1

    您可以确保 Columms 的值是 T 的键或使用此类型接受 T 的函数:

    interface Columns<T> {
        [s: string]: keyof T | ((item: T) => string);
    }
    const exportAsCsv = function <T>(data: T[], columns: Columns<T>): void {
       //...
    }
    const users = [{ id: 1, name: 'Alice', isCool: true }];
    exportAsCsv(users, {
        'Id': 'id',
        'Name': 'name',
        'Is cool': u => u.isCool ? 'Yes' : 'No',
    });
    exportAsCsv(users, {
        'Id': 'id',
        'Name': 'name2', // error 
        'Is cool': u => u.isCooll ? 'Yes' : 'No', //error
    });
    

    您也可以与调用分开创建列,但需要指定 T

    const users = [{ id: 1, name: 'Alice', isCool: true }];
    const columns : Columns<typeof users[number]> = {
        'Id': 'id',
        'Name': 'name',
        'Is cool': u => u.isCool ? 'Yes' : 'No',
    };
    exportAsCsv(users, columns);
    

相关问题