我有以下内容
export type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
type A = {
f1?: string;
};
function test(a: A): WithRequired<A, 'f1'> {
if (a.f1) {
return a;
} else {
throw Error();
}
}
但是,这会产生错误
Type 'A' is not assignable to type 'WithRequired<A, "f1">'.
Type 'A' is not assignable to type '{ f1: string; }'.
Types of property 'f1' are incompatible.
Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.
我想我希望它能起作用,因为在这个分支的上下文中,编译器知道 a.f1 不是未定义的......并且在某些上下文中,打字稿将正确地执行此操作。
我想我有两个问题
'a' 不是您返回的类型,因此您必须在代码中对其进行强制转换。另一种方法是使用 type 谓词:
type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
type A = {
f1?: string;
};
function isWithRequired<T, K extends keyof T>(obj: T, k: K): obj is WithRequired<T,K> {
return Boolean(obj[k]);
}
function test(a: A): WithRequired<A, 'f1'> {
if(isWithRequired(a, 'f1')){
return a;
} else {
throw Error();
}
}
function testF<T,K extends keyof T>(obj: T, k: K): WithRequired<T,K> {
if(isWithRequired(obj, k)) {
return obj;
} else {
throw Error();
}
}
const a1:A = {};
const a2:A = {f1: 'xyz'};
try {
const test1 = testF(a1, 'f1');
console.log('>> test1: ', test1);
} catch {
console.log('test1 failed');
}
try {
const test2 = testF(a2, 'f1');
console.log('>> test2: ', test2);
} catch {
console.log('test2 failed');
}
一旦进入类型谓词的 if 块,编译器就会假定该谓词类型。
我修改了你的原始函数并添加了第二个
testF
,它是通用的,也就是说,你可以向它传递对象和字段(而不是特定于类型“A”)