假设我有一个接收原始数据的通用函数,以及一个解析器数组以生成一个简单对象
function parseData<T extends object>(
rawData: any,
...parsers: Array<{
field: keyof T
parser(rawData: any): any
}>
): T {
// Loop through and generate object
}
函数调用看起来像
interface ResultData {
name: string,
age: number
}
const result = parseData<ResultData>(
rawData,
{ field: 'name', parser: nameParser },
{ field: 'age', parser: ageParser }
)
field
的类型检查效果很好。如果我输入的不是name
或age
,我会得到预期的语法错误。我想知道是否有一种方法可以确保解析器结果是该特定字段的正确值类型。例如,如果我尝试将{ field: 'name', parser: ageParser }
作为解析器之一传递,我想接收语法错误
答案 0 :(得分:1)
您可以做一些接近您想要的事情,但是它涉及添加需要推断的类型参数,并且由于TypeScript当前不允许specifying some type paremters while allowing others to be inferred,(但是即将出现soon),因此trick,您可以同时使用它。
首先,让我们使用mapped type和lookup来生成类型:
的可能的解析器类型的并集,假设“原始数据”的类型为>>> a = np.array([[1,2,3], [1,1,1], [1,1,1]])
# 1: and :2 all_indices_after_1 and all_indices_before_2 respectively
>>> a[1:,:2] = np.array([[888,888], [99, 99]])
>>> a
array([[ 1, 2, 3],
[888, 888, 1],
[ 99, 99, 1]])
:
T
然后,将R
函数设置为用户指定的type Parsers<T, R> = { [K in keyof T]: { field: K, parser(rawData: R): T[K] } }[keyof T];
值,以及对应于parseData()
的{{1}}值和tuple rest parameter键入与T
对应的R
。该功能的实现留给您:
rawData
现在让我们看看它是否有效:
P
这看起来不错,如果切换到其他位置,则应该失败:
parsers
如果不使用解析器,它将不会失败:
declare function parseData<T extends object>(): <R, P extends Parsers<T, R>[]>(
rawData: R,
...parsers: P
) => T;
所以您要么希望输出是interface ResultData {
name: string,
age: number
}
const resultDataParse = parseData<ResultData>(); // T is now ResultData
// call parser:
const result = resultDataParse(
"hello",
{ field: 'name', parser: (x: string) => x + "!" },
{ field: 'age', parser: (x: string) => x.length }
);
而不是const oops = parseData<ResultData>()(
"hello",
{ field: 'name', parser: (x: string) => x + "!" },
{ field: 'age', parser: (x: string) => x + "!" } // error, string not number
)
,要么想要以某种方式约束const noError = parseData<ResultData>()(
"hello",
{ field: 'name', parser: (x: string) => x + "!" },
)
以要求所有解析器;但这不是问题,我必须运行。 ♂️
希望有帮助。祝你好运!