typescript - 未在接口中推断的打字稿泛型函数参数
问题描述
我正在尝试构建一个表接口,该接口提供对表列具有的值的严格键入以及对列值执行并返回字符串的函数。但是,我在函数参数中使用泛型时遇到问题。下面是我正在做的一个简单示例。我正在使用 Typescript 3.9.5
/**
* Interface for of a single column
*/
interface ColumnInfo<T, K extends keyof T> {
column: K,
cellFactory: (value: T[K]) => string
}
/**
* Interface for all table columns. Only single row for debugging purposes.
*/
interface Columns<T> {
columns: ColumnInfo<T, keyof T>;
};
/**
* Row implementation
*/
type RowImpl = {
id: string;
c1: string; //Could be number, Date, etc, simplified for now
c2: string;
}
/**
* id column implementation
*/
const columnInfo: ColumnInfo<RowImpl, 'id'> = {
column: 'id',
cellFactory: () => ''
}
/**
* Table columns Implementation. Currently only accepting a single column for debugging
*/
const columns: Columns<RowImpl> = {
columns: columnInfo
}
我目前在列对象上遇到错误,说明...
类型 'ColumnInfo<RowImpl, "id">' 不可分配给类型 'ColumnInfo<RowImpl, "id" | "c1" | "c2">'。输入'"id" | "c1" | "c2"' 不能分配给类型 '"id"'。类型 '"c1"' 不可分配给类型 '"id"'.ts(2322)
我不确定为什么在我使用 T[K] 时它试图将联合分配给特定类型。我将 cellFactory 对象简化为 T[K] 以缩小问题范围,但它现在可以工作了。
interface ColumnInfo<T, K extends keyof T> {
column: K,
cellFactory: T[K]
}
/**
* Interface for all table columns. Only single row for debugging purposes
*/
interface Columns<T> {
columns: ColumnInfo<T, keyof T>;
};
/**
* Row implementation
*/
type RowImpl = {
id: string;
c1: number;
c2: string;
}
/**
* id column implementation
*/
const columnInfo: ColumnInfo<RowImpl, 'id'> = {
column: 'id',
cellFactory: ''
}
/**
* Table columns Implementation. Currently only accepting a single column
*/
const columns: Columns<RowImpl> = {
columns: columnInfo
}
使用 cellFactory 作为 T[K] 而不是 (val: T[K]) => string 它可以工作。为什么是这样?我假设它是否可以推断出 T[K] 两个示例都应该有效,但函数参数不是。有人可以解释我的问题是什么以及我需要更改什么才能获得工作界面吗?
谢谢
解决方案
当您尝试定义一个可用于多个不同列的对象时,问题就开始出现了。
interface Columns<T> {
columns: ColumnInfo<T, keyof T>;
};
这里keyof T
是 的所有键T
,而不仅仅是一个特定的键。
当您尝试将更具体的实例分配给更columnInfo: ColumnInfo<RowImpl, 'id'>
广泛的类型ColumnInfo<RowImpl, keyof RowImpl>
时,该column
属性很好,因为id
可以分配给keyof RowImpl
。
问题在于回调。更广泛的类型ColumnInfo<RowImpl, keyof RowImpl>
需要一个接受RowImpl
对象所有可能值的回调,但是你给它一个只能接受一种特定类型的函数。所以cellFactory: (value: RowImpl['id']) => string
不能赋值给cellFactory: (value: RowImpl[keyof RowImpl]) => string
。
如果您要扩大ColumnInfo
对象value
的任何值,那么错误就会消失。但我不建议这样做,因为我们会丢失有关特定列类型的信息。
interface ColumnInfo<T, K extends keyof T> {
column: K,
cellFactory: (value: T[keyof T]) => string
}
我自己处理过这个特殊问题,我的解决方案是使用映射对象类型,其中键的columnInfo
键与RowImpl
. 这允许我们声明ColumnInfo
给定键的 只能用于该列。我们不需要扩大到,keyof T
所以我们避免了错误。
type Columns<T> = {
[K in keyof T]?: ColumnInfo<T, K>;
};
const columns: Columns<RowImpl> = {
id: columnInfo, // ok
c1: columnInfo, // error: Type '"id"' is not assignable to type '"c1"'
}
推荐阅读
- python - 带有网络身份和转发的python登录门户
- python - 删除 pyplot.hist() 中的背景绘图线
- python - 有没有办法下载 PoseNet 的冻结图(.pb 文件)?
- javascript - 使用 Slick Slide 触发按钮单击时的滑块不起作用?
- python - 加载 tkinter 应用程序后尝试启动另一个进程时出现 Python 错误
- android - 通过Sqlite在Android Studio中获取数据的静态方法错误
- javascript - 返回点数组中最近添加的点的颜色
- android - Android GridLayoutManager 一整行的背景图片
- node.js - 我如何添加除 multer-gridfs-storage 默认属性以外的新字段
- java - 是否可以扩展解决方案类?