代码之家  ›  专栏  ›  技术社区  ›  Svish

如何在typescript中表示“以t为参数的函数字符串,它是t的键”

  •  1
  • Svish  · 技术社区  · 6 年前

    我有下面的打印脚本,它可以工作:

    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"));
    }
    

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

    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 回复  |  直到 5 年前
        1
  •  1
  •   marc_s Anurag    5 年前

    您可以确保 Columns 或者是 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.isCool ? '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);