gpt4 book ai didi

typescript - 仅接受数组值键(并推导返回类型)的函数

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

我正在尝试理解新的 conditional types在 typescript 2.8 中。

例如,我有一些具有数组属性的对象,在我的流程中必须只有一个元素,我想获得这个值。这是 code I thought should work ,它正确地只允许传入相关属性,但我不知道如何指定返回类型。我收到以下编译错误:

Type number cannot be used to index type Pick<T, { [K in keyof T]: T[K] extends any[] ? K : never; }[keyof T]>[K].

以及 n 的类型和 s推导为 number|string而不是 number对于 nstring对于 s .

代码如下:

type ArrayProperties<T> = Pick<T, {
[K in keyof T]: T[K] extends Array<any>? K : never
}[keyof T]>;

const obj = {
a: 4,
n: [2],
s: ["plonk"]
};

// Compilation error on next line
function single<T, K extends keyof ArrayProperties<T>>(t: T, k: K): ArrayProperties<T>[K][number] {
const val = t[k];
if (!Array.isArray(val))
throw new Error(`Expected ${k} to be an array`);

if (val.length !== 1)
throw new Error(`Expected exactly one ${k}`);

return val[0];
}

const n = single(obj, "n"); // 'n' should be of type 'number'
const s = single(obj, "s"); // 's' should be of type 'string'
const a = single(obj, "a"); // Should fail to compile (OK)

最佳答案

您可以使用一些解决方法来实现这一点。

修复报告的错误:

要强制 TypeScript 编译器在无法验证属性是否存在时查找该属性,您可以将键类型与已知键相交。像这样:

type ForceLookup<T, K> = T[K & keyof T]; // no error

所以你可以改变

ArrayProperties<T>[K][number]

ForceLookup<ArrayProperties<T>[K],number>

让我们确保它有效:

type N = ForceLookup<ArrayProperties<typeof obj>["n"],number>; // number ✔️
type S = ForceLookup<ArrayProperties<typeof obj>["s"],number>; // string ✔️

n 推断更窄的类型和 s :

问题是 K未被推断为字符串文字。要提示编译器应尽可能为类型参数推断字符串文字,您可以添加约束 extends string .它没有很好的记录,但在特殊情况下 TypeScript infers literal types而不是扩大到更一般的类型(所以当 1 被推断为 1 而不是 number 时,或者当 'a' 被推断为 'a' 而不是 string 时)。禁忌症keyof ArrayProperties<T>显然不会触发这种非扩大,所以K扩大到keyof ArrayProperties<T>在所有情况下。这是 K 的解决方法:

K extends string & keyof ArrayProperties<T>

让我们看看这一切:

declare function single<T, K extends string & keyof ArrayProperties<T>>(
t: T, k: K): ForceLookup<ArrayProperties<T>[K],number>;
const n = single(obj, "n"); // number ✔️
const s = single(obj, "s"); // string ✔️
const a = single(obj, "a"); // still error ✔️

全部完成!


好吧,我会在这里做一些简化。 ArrayProperties<T>[K]可以减少到T[K] , 对于任何 K你可以实际使用。所以你得到:

declare function single<T, K extends string & keyof ArrayProperties<T>>(
t: T, k: K): ForceLookup<T[K],number>;

现在一切都完成了。


希望对您有所帮助。祝你好运!

关于typescript - 仅接受数组值键(并推导返回类型)的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49550929/

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