gpt4 book ai didi

typescript - 我可以在 typescript 中为 keyof 参数提供默认值吗?

转载 作者:行者123 更新时间:2023-12-04 17:34:41 27 4
gpt4 key购买 nike

尝试在必须是传递对象的属性的泛型方法上强制执行可选的默认参数。这是一个例子:

function doIt<T>(target: T, propA: keyof T, propB: keyof T): string {
return `${target[propA]} ${target[propB]}`;
}

但是,在上面的示例中,我想将 propApropB 默认为 foobar例如:

function doIt<T>(target: T, propA: keyof T = 'foo', propB: keyof T = 'bar'): string {
return `${target[propA]} ${target[propB]}`;
}

但是当我这样做时,它会提示 Type '"bar"' is not assignable to type 'keyof T'.ts(2322) 这是有道理的。即使我将默认类型添加到 T,它仍然不起作用:

function doIt<T = { foo: string; bar: string }>(target: T, propA: keyof T = 'foo', propB: keyof T = 'bar'): string {
return `${target[propA]} ${target[propB]}`;
}

基本上,我希望能够做到:

doIt({foo: 'jane', bar: 'doe'}); // should return 'jane doe'
doIt({zoo: 'jane', baz: 'doe'}); // should fail compilation
doIt({zoo: 'jane', baz: 'doe'}, 'zoo', 'baz'}); // should return 'jane doe'

有什么办法吗?

最佳答案

如果不与类型检查器发生冲突,您不能轻易地为此使用默认参数值。

获得所需内容的最简单方法可能是使用 overloads描述调用 doIt() 的不同预期方式,如下所示:

namespace Overloads {
function doIt<T>(target: T, propA: keyof T, propB: keyof T): string;
function doIt<T extends { bar: any }>(target: T, propA: keyof T): string;
function doIt<T extends { foo: any; bar: any }>(target: T): string;
function doIt(target: any, propA?: keyof any, propB?: keyof any): string {
if (typeof propA === "undefined") propA = "foo";
if (typeof propB === "undefined") propB = "bar";
return `${target[propA]} ${target[propB]}`;
}

console.log(doIt({ foo: "jane", bar: "doe" })); // jane doe
console.log(doIt({ zoo: "jane", baz: "doe" })); // error!
// ┌─────────────> ~~~~~~~~~~~~
// "zoo" not expected (although I'm surprised it doesn't complain about missing foo/bar)
console.log(doIt({ zoo: "jane", baz: "doe" }, "zoo", "baz")); // jane doe
console.log(doIt({ zoo: "jane", bar: "doe" }, "zoo")); // jane doe
}

一切如您所愿。注意这三个调用签名对应不同数量的参数,它们各自有不同的constraints。在泛型类型参数 T 上。 (您可能希望使用 string 而不是 any 作为属性类型,那里...不确定)

请注意,在实现签名中,我将 target 作为 anypropApropB 作为(任意键)|未定义。所以这里的实现不会特别安全。重载并不能真正帮助实现类型安全;它们更多地是为了调用者的利益。如果您尝试使实现通用化,您会遇到类似的问题,即编译器无法验证 "foo" 是否可分配给 keyof T,等等。

另请注意,我们不能在重载签名中使用默认参数值,但这没关系……我们可以在函数实现中自己进行赋值。如果参数未定义,请重新分配它们。


另一种方法是使用 TypeScript 对处理 rest parameters as tuple types 的支持, 包括 optional tuple elements :

namespace ConditionalTupleParameters {
function doIt<T>(
target: T,
...[propA, propB]: T extends { foo: any; bar: any }
? [(keyof T)?, (keyof T)?] // propA and propB are optional
: T extends { bar: any }
? [keyof T, (keyof T)?] // propA is required, propB is optional
: [keyof T, keyof T] // propA and propB are optional
): string {
if (typeof propA === "undefined") propA = "foo";
if (typeof propB === "undefined") propB = "bar";
return `${target[propA]} ${target[propB]}`;
}

console.log(doIt({ foo: "jane", bar: "doe" })); // jane doe
console.log(doIt({ zoo: "jane", baz: "doe" })); // error!
// ┌──────> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// expected 3 arguments, got 1
console.log(doIt({ zoo: "jane", baz: "doe" }, "zoo", "baz")); // jane doe
console.log(doIt({ zoo: "jane", bar: "doe" }, "zoo")); // jane doe
}

这与重载类似。它看起来相当丑陋,这不是很好。但是,该实现实际上是相对类型安全的,其中 target 仍然是 T 类型,propApropB 在检查 undefined 后最终成为 keyof T


好的,希望其中之一对您有所帮助。祝你好运!

Link to code

关于typescript - 我可以在 typescript 中为 keyof 参数提供默认值吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57151263/

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