将 JSON 对象转换为忽略打字稿中区分大小写的接口

时间:2021-03-01 22:24:11

标签: typescript

当 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;    
}

1 个答案:

答案 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
相关问题