TypeScript:强制一致的对象键作为类型参数

TypeScript:强制一致的对象键作为类型参数,typescript,Typescript,我有一个列界面,可以根据键渲染行中的值: interface Column<Row, Field extends keyof Row> { key: Field; render: (value: Row[Field]) => React.ReactNode; } 由于字段被实例化为用户的键,而不是特定的键。啊,我喜欢这种类型的问题。您遇到的一个问题是TypeScript不允许您省略类型参数和。您可以说类似于列,其中行类型参数是从您传递给它的对象文本推断出来的。

我有一个
界面,可以根据键渲染行中的值:

interface Column<Row, Field extends keyof Row> {
    key: Field;
    render: (value: Row[Field]) => React.ReactNode;
}

由于
字段
被实例化为用户的
,而不是特定的键。

啊,我喜欢这种类型的问题。您遇到的一个问题是TypeScript不允许您省略类型参数和。您可以说类似于
,其中
类型参数是从您传递给它的对象文本推断出来的。我们不能直接这么做。。。但我们可以间接获得这种效果:

function columnsFor<Row>() {
  function of<Field extends keyof Row>(column: Column<Row, Field>): Column<Row, Field> {
    return column;
  }
  return of;
}
userColumn
函数将只接受某个
Column
类型的参数,并从该参数推断
字段
。现在,您可以继续制作该阵列:

const columns = [
  userColumn({
    key: "id",
    render(id: number) {
      return id;
    }
  }), // ok, inferred as Column<User,"id">
  userColumn({
    key: "name",
    render(name: string) {
      return name;
    }
  }), // ok, inferred as Column<User,"name">
  userColumn({
    key: "id",
    render(id: string) {
      return id;
    }
  }) // error as expected
];
const列=[
用户列({
密钥:“id”,
渲染(id:编号){
返回id;
}
}),//确定,推断为列
用户列({
键:“名称”,
渲染(名称:字符串){
返回名称;
}
}),//确定,推断为列
用户列({
密钥:“id”,
渲染(id:字符串){
返回id;
}
})//错误如预期
];

希望这对你有用。祝你好运

联合类型如何:id:number | string;看一看:我不确定这有什么帮助:我希望TypeScript只允许
id:number
作为参数。哦,好的。不过我不明白你的问题。谢谢,我怀疑这样的事情可能会发生,但我不确定TypeScript中的惯用方法是什么。我希望有一种方法可以保证使用类型系统的正确使用,因为仍然有可能产生不正确的代码。如果TypeScript具有不透明类型,则可以通过使
不透明来使用此方法,这样所有列都必须使用
columnFor
创建。您可以使
Column
成为一个具有私有构造函数的类,并为其提供一个静态方法,以仅生成所需的
对象。上面的代码并不完全是错误的;你告诉TypeScript你想要一个
数组,这不是你真正的意思。谢谢,我来看看私有构造函数。至于原始代码是否正确:我认为该列不是
列的有效实例
function columnsFor<Row>() {
  function of<Field extends keyof Row>(column: Column<Row, Field>): Column<Row, Field> {
    return column;
  }
  return of;
}
const userColumn = columnsFor<User>();    

const goodColumn = userColumn({
  key: "id",
  render(id: number) {
    return id;
  }
}); // ok, inferred as Column<User, "id">

const badColumn = userColumn({
  key: "id",
  render(id: string) {
    return id;
  }
}); // error as expected 
const columns = [
  userColumn({
    key: "id",
    render(id: number) {
      return id;
    }
  }), // ok, inferred as Column<User,"id">
  userColumn({
    key: "name",
    render(name: string) {
      return name;
    }
  }), // ok, inferred as Column<User,"name">
  userColumn({
    key: "id",
    render(id: string) {
      return id;
    }
  }) // error as expected
];