gpt4 book ai didi

typescript - 输入安全字段分配

转载 作者:行者123 更新时间:2023-12-03 16:10:21 25 4
gpt4 key购买 nike

我想基于这样的一些条件为对象的字段分配一个数字:

function maybeANumber(): number | undefined {
const n = Math.random();
return n > 0.5 ? n : undefined;
}

function maybeSetNumber(target: any, field: any) {
const num = maybeANumber();
if (num !== undefined) {
target[field] = num;
}
}
之所以有效,是因为我自由地使用了 any,但是如何正确键入它,以便它检测到类型错误:

interface Foo {
a: string,
b: number,
}

const foo: Foo = { a: "", b: 0 };

maybeSetNumber(foo, "a"); // Should be a compile-time error.
maybeSetNumber(foo, "b"); // Should be a ok.
有什么办法吗?
编辑:重要说明:字段名称是静态的。我不需要它来处理任意字符串。我用 keyof尝试了很多东西,但还不太清楚。

最佳答案

您可以在maybeSetNumber()签名中使用generics来表示field是通用属性 key 类型(K extends PropertyKey),而target是在该 key 处具有number值的类型(Record<K, number>使用 Record 实用程序类型):

function maybeSetNumber<K extends PropertyKey>(target: Record<K, number>, field: K) {
const num = maybeANumber();
if (num !== undefined) {
target[field] = num;
}
}
这将给出您想要的行为:
maybeSetNumber(foo, "a"); // error!
// ----------> ~~~
// Types of property 'a' are incompatible.
maybeSetNumber(foo, "b"); // okay
警告:TypeScript并不是完美的 sound,因此,如果您开始使用比 number窄的类型,这仍然会让您做一些不安全的事情:
interface Oops { x: 2 | 3 }
const o: Oops = { x: 2 };
maybeSetNumber(o, "x"); // no error, but could be bad if we set o.x to some number < 1
也可以进行签名,使上面的错误出现在 "a"而不是 foo上。这种方式更加复杂,并且至少需要一个类型声明,因为编译器无法理解其含义:
type KeysMatching<T, V> = { [K in keyof T]: V extends T[K] ? K : never }[keyof T]
function maybeSetNumber2<T>(target: T, field: KeysMatching<T, number>) {
const num = maybeANumber();
if (num !== undefined) {
target[field] = num as any; // need a type assertion here
}
}

maybeSetNumber2(foo, "a"); // error!
// ----------------> ~~~
// Argument of type '"a"' is not assignable to parameter of type '"b"'.
maybeSetNumber2(foo, "b"); // okay
Oops不会遇到相同的问题,
maybeSetNumber2(o, "x"); // error!
但是围绕稳健性可能仍然存在一些边缘情况。 TypeScript经常假设,如果您可以从属性读取 X类型的值,则可以向该属性写入 X类型的值。除非没有问题,否则这很好。无论哪种情况,它们都比 any更好。
Playground link to code

关于typescript - 输入安全字段分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64035397/

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