当 json 的某些成员与接口的成员仅区分大小写时,是否有任何方法可以将 jsonObj“转换”为某个接口?
interface Desire {
propTest1: string,
propTest2: string
}
let jsonFromApi = {
PropTest1: "aa",
PropTest2: "bb"
}
let result = smartCast<Desire>(jsonFromApi);
console.log(results)
// I expect {
propTest1: "aa",
propTest2: "bb"
}
这是我迄今为止尝试过的:
function smartCast<T>(from: object): T{
type LOWERCASE = { [p in keyof T & string as Lowercase<`${p}`>]: T[p] }
type LOWERCASE_MAP = { [p in keyof T & string as Lowercase<`${p}`>]: p }
const lowerCase = Object.entries(from).reduce((a: any, [key, val]) => {
a[key.toLowerCase()] = val;
return a;
}, {}) as LOWERCASE;
console.log("lowercase ", lowerCase)
const lowerCaseMap = Object.entries(lowerCase).reduce((a: any, [key, val]) => {
a[key] = key;// how to get something like LOWERCASE_MAP[key] ?? typescript === runtime without types :(((
return a;
}, {});
return Object.entries(lowerCase).reduce((a: any, [key, val]) => {
a[lowerCaseMap[key]] = val
}, {}) as T;
}
答案 0 :(得分:1)
您想更改在运行时从 API 获取的 JSON 对象的属性大小写。但是最初来自对象的打字稿定义在哪里?解析 JSON 通常会在设计时为您提供 any
类型,除非您使用已返回类型对象的 API 库。
如果您没有类型定义或无论如何您要手动重新创建它们,只需将案例修改函数的返回类型设置为此类型即可。您不需要为此使用打字稿的泛型:
type AnyObject = {[index: string]: unknown};
interface DesiredResultObject {
prop1: string;
prop2: number;
}
const jsonObject = {
Prop1: "answer",
Prop2: 42,
}
function toLowerCaseProps(obj: AnyObject): DesiredResultObject {
return Object.entries(obj).reduce((a, [key, val]) => {
a[key.toLowerCase()] = val;
return a;
}, {} as AnyObject) as unknown as DesiredResultObject;
}
const result = toLowerCaseProps(jsonObject);
如果您已经有了 API 对象的类型定义,并且想要转换它们的键但不想手动创建新的类型,您可以执行以下操作:
type AnyObject = {[index: string]: unknown};
type LowerCaseProps<T extends AnyObject> = {
[K in keyof T as Lowercase<string & K>]: T[K]
};
const jsonObject = {
Prop1: "answer",
Prop2: 42
}
function toLowerCaseProps<T extends AnyObject>(obj: T): LowerCaseProps<T> {
return Object.entries(obj).reduce((a, [key, val]) => {
a[key.toLowerCase()] = val;
return a;
}, {} as AnyObject) as LowerCaseProps<T>;
}
const result = toLowerCaseProps(jsonObject);
console.log(result.prop1); // outputs "answer"
// console.log(result.Prop1); // this won't compile
console.log(result.prop2); // outputs 42
// console.log(result.Prop2); // this won't compile