gpt4 book ai didi

typescript - 我如何要求 keyof 用于特定类型的属性?

转载 作者:搜寻专家 更新时间:2023-10-30 21:27:39 25 4
gpt4 key购买 nike

我正在尝试编写一个通用函数,它可以通过键名切换任何对象中的 bool 属性。我读了release notes for TypeScript-2.8并认为条件类型应该可以解决此类问题。但是,我不知道如何编写我的函数。

我的函数接受要修改的对象和要修改的键的名称。为了确保只传入 bool 属性的键,我使用了条件类型表达式 T[K] extends boolean ? K:从不。据我了解,如果我尝试为非 bool 属性传递 key ,这应该会导致错误,因为 T[K] 不满足 extends boolean。但是,如果我尝试为 bool 值传递 key ,那么它应该接受 K

然而,即使有这个条件,TypeScript 似乎也没有在函数内意识到 T[K] extends boolean 必须为真。所以我无法将从对象读取的值赋值回对象。这会导致下面显示的第一个错误。第二个错误是类型推断似乎对我的函数不起作用。在下面的调用中,到目前为止只有第二个调用通过了 TypeScript 的检查。

function invertProperty<T, K extends keyof T> (o:T, propertyName:(T[K] extends boolean ? K : never)) {
o[propertyName] = !o[propertyName]; // Type 'false' is not assignable to type 'T[T[K] extends boolean ? K : never]'. [2322]
}

const myObject:IObject = {
a: 1,
b: true,
c: 'hi',
};

invertProperty(myObject, 'b'); // Argument of type '"b"' is not assignable to parameter of type 'never'. [2345]
invertProperty<IObject, 'b'>(myObject, 'b'); // Works, but requires me to type too much.
invertProperty(myObject, 'a'); // Argument of type '"a"' is not assignable to parameter of type 'never'. [2345]
invertProperty<IObject, 'a'>(myObject, 'a'); // Argument of type '"a"' is not assignable to parameter of type 'never'. [2345]

interface IObject {
a:number,
b:boolean,
c:string,
}

我认为,如果在我的 K extends keyof T 类型约束中,我也可以声明 and T[K] extends boolean 它会做正确的事情。在我看来,这是一个问题,我试图在参数类型中使用 never 而不是能够约束类型参数。但我找不到任何方式来表达这一点。

关于如何在完全类型安全的情况下实现这一点有什么想法吗?

最佳答案

首先,您可以使用此构造提取 bool 属性的所有键(它将非 bool 值的键转换为 never 并采用所有键/never 的联合,使用 T | neverT):

type BooleanKeys<T> = { [k in keyof T]: T[k] extends boolean ? k : never }[keyof T];

然后,为了使 TypeScript 乐于为属性分配 bool 值,您引入了声明为仅具有 bool 属性的中间类型(不幸的是,TypeScript 无法自行解决这部分问题)

type OnlyBoolean<T> = { [k in BooleanKeys<T>]: boolean };

并且您声明 invertProperty 的泛型类型参数与 OnlyBoolean 兼容(确实如此,它可能包含额外的非 bool 属性,但没关系)

注意您可能需要不同版本的代码,具体取决于编译器的版本,此答案中的原始代码已停止使用 TypeScript 3.2:

// for TypeScript 3.1 or earlier
function invertProperty<T extends OnlyBoolean<T>>(o: T, propertyName: BooleanKeys<T>) {
o[propertyName] = !o[propertyName];
}

// for TypeScript 3.2 or later
function invertProperty<T>(o: OnlyBoolean<T>, propertyName: keyof OnlyBoolean<T>) {
o[propertyName] = !o[propertyName];
}


interface IObject {
a: number;
b: boolean;
c: string;
}
const myObject:IObject = {
a: 1,
b: true,
c: 'hi',
};



invertProperty(myObject, 'b'); // ok
invertProperty(myObject, 'a'); // error

关于typescript - 我如何要求 keyof 用于特定类型的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50851263/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com