gpt4 book ai didi

javascript - 如何在Typescript中获取特定 "keyof"参数的类型?

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

我想定义一个适配器架构,将一个对象转换为另一个。

export type AdapterSchema<Source, Destination> = {
[key in keyof Partial<Source>]: {
target: keyof Destination;
convert: (source: Source[key]) => Destination[keyof Destination];
};
};
应该可以添加一个转换函数,将属性的值转换为目标属性的值。
interface Foo {
a : string;
}

interface Bar {
b : number;
c : string;
}

const schema : AdapterSchema<Foo,Bar> = { a : {target: 'b', convert: (value) => 'x'}}
我希望编译器在这里抛出错误,因为“x”不是数字类型。我的类型至少有点类型安全,因为只允许 Bar 类型,但不会抛出错误,因为 Bar 也有一个 string 类型的属性。
这可以使类型更安全吗?
提前致谢。

最佳答案

您将需要更改 AdapterSchema<S, D>,以便每个属性都是 target 类型中每个键 convert 的不同可能 KD/D 对的 union
也就是说,无论 AdapterSchema<S, D> 是什么,您都希望 AdapterSchema<Foo, Bar> 评估为:

type ASFB = AdapterSchema<Foo, Bar>;
/* type ASFB = {
a?: {
target: "b";
convert: (source: string) => number;
} | {
target: "c";
convert: (source: string) => string;
} | undefined;
} */
我们可以通过更改您的版本来做到这一点(稍微重写,但它是相同的):
type OrigAdapterSchema<S, D> = {
[KS in keyof S]?: {
target: keyof D;
convert: (source: S[KS]) => D[keyof D];
};
};
到以下版本:
type AdapterSchema<S, D> = {
[KS in keyof S]?: ({ [KD in keyof D]-?: {
target: KD;
convert: (source: S[KS]) => D[KD];
} }[keyof D]);
}
这是通过构建一个 mapped type 来工作的,其中 KD 的每个键 D 都被赋予一个属性,其中 targetKD 并且 convert 的返回类型是 D[KD] ...然后立即将 indexingkeyof D 放入其中以获得属性的联合。
您现在可以验证 AdapterSchema<Foo, Bar> 是否为所需类型。现在编译器按照您的意愿运行:
const badSchema: AdapterSchema<Foo, Bar> = {
a: { target: 'b', convert: (value) => 'x' } // error!
// ~~~~~~ <-- b is not assignable to c
}

const schema: AdapterSchema<Foo, Bar> = {
a: {
target: "b",
convert: v => v.length
}
}; // okay
(请注意,此解决方案不会强制 AdapterSchema<S, D> 真正生成 D 中的每个属性;例如 {} 是可接受的 AdapterSchema<Foo, Bar> ,或者您可以将 S 中的每个属性映射到 D 中的相同属性。但您的问题与此无关,所以对此的任何答案都超出了此处的范围。)
Playground link to code

关于javascript - 如何在Typescript中获取特定 "keyof"参数的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68376925/

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