[尝试正确获取以下TypeScript类型表达式以使其具有本地尝试编写一个名为getValue(string, defValue?)
的类型智能函数,如果找不到该密钥,则该函数将返回字符串或默认值。该函数的类型应为string | typeof defaultValue
,lookupValue()函数应具有正确的类型来支持此功能。
至此,已经尝试了该方法的4种不同的变体,其中三种在编译或使用中均失败,最后一种情况不能完全处理类型输入,但可以编译。
// This function is good -- correctly handling the types
lookupValue<D>(record: string[], key: string, defvalue: D): D | string {
const index = this.columnHeaders[key];
const v = index !== undefined ? record[index] : undefined;
return v === undefined || v === "" ? defvalue : v.trim();
}
someFunction(record: string[]) {
// -- Test 1
const getValue = <T>(key: keyof typeof COLUMNS, defvalue = undefined) => lookupValue(record, key, defvalue);
// Argument of type '""' is not assignable to parameter of type 'undefined'.
const bigDef = getvalue("testBig", "something");
// -- Test 2
// Type 'undefined' is not assignable to type 'T'.
const getValue = <T>(key: keyof typeof COLUMNS, defvalue: T = undefined) => lookupValue(record, key, defvalue);
// -- Test 3
// Won't compile since the defvalue is "T | undefined" which isn't valid
const getValue = <T>(key: keyof typeof COLUMNS, defvalue?: T) => lookupValue(record, key, defvalue);
// -- Test 4
// Compiles but is wrong since the following getValue "works"
const getValue = <T = undefined>(key: keyof typeof COLUMNS, defvalue?: T) => lookupValue(record, key, defvalue as T);
// Works - but shouldn't
const foo: string = getValue("test");
}
目标是要有满足此要求的东西:
const big = getvalue("testBig"); // Should be type of string | undefined
const bigDef = getvalue("testBig", "something"); // Should be type string
<generic> | undefined
。例如:function doSomething<A>(param1?: A) {
return param1;
}
在这种情况下,param1为“ A |未定义”。这会破坏所有类型的流程,因为通用方面不包括未定义方面,而是坚持使用了它-即使在您不带参数调用doSomething()
的情况下也是如此。因此,doSomething(“ jello”)的结果为string | undefined
;这很愚蠢,因为人们会认为这将是字符串。doSomething()
的返回类型为{} | undefined
而不只是undefined
也是这种情况。您有时可以通过用大隐喻的锤子用力敲打打字稿来解决此问题。通常,锤子包括制定正确的类型定义,然后投射所有抱怨的内容。没有一个适合所有人的尺码,但您可以这样做:
const getValue = <R = string, A = undefined>(key: string, defvalue: A = (undefined as unknown) as A): R | A => (lookupValue(record, key, defvalue) as unknown) as R | A;
首先,将R和A设置为字符串,并且默认情况下未定义。这样一来,如果编译器没有其他可用信息,则假定R / A是字符串/未定义。然后,必须设置defvalue: A
以阻止编译器添加| undefined
。没有| undefined
,编译器可以进行代数输入。然后,您必须指定函数的结果为R | A
,因为这基本上就是您想要的。下一步是告诉编译器停止基于对lookupValue的调用结果来推断“ A”是什么,因为它将错误地进行推断。这也是为什么我们需要使用“ R”而不是string | A
的原因。本质上,如果您不区分lookupValue的结果(或使用字符串| A作为结果类型),则编译器非常聪明,可以看到类型信息不足,因此,取决于如果将getValue
的返回类型设置为string | A
,则将结果放入其中并不能编译(如果省略强制转换)或失败,如下所示
const result: string = getValue("testBig");
“ A”会推断出错误的字符串,因为它应该是编译错误。“”无法分配字符串|未定义为字符串”。另一种情况:
const result: string = getValue("testBig");
[A
会推断为undefined
,这意味着const result
将是string | undefined
类型,这也是错误的。为了避免上述情况,我们在第二行添加
as unknown) as R | A
以获得:
const getValue = <R = string, A = undefined>(key: string, defvalue: A = (undefined as unknown) as A): R | A => (lookupValue(record, key, defvalue) as unknown) as R | A;
我能想到的所有情况下都可以正常工作
// ss is number | string const ss = getValue("testBig", 1); // bigDef is string const bigDef = getValue("testBig", "something"); // sdf is string | undefined const sdf = getValue("testBig", undefined); const sdf = getValue("testBig"); // Compile error -> string | undefined can't be assigned to string const asdfa: string = getValue("testBig");