ts该怎么定义这个函数的返回值, 才能看到obj1的具体类型推断呢?

image.png
function getMapObj(originObj, keyArr) {
  // let originObj = JSON.parse(JSON.stringify(originObj))
  let obj = {}
  keyArr = keyArr.filter(Boolean)
  Object.keys(originObj).filter(v => keyArr.includes(v)).forEach(v => {
    obj[v] = originObj[v]
  })
  return obj
}
let obj = {
  a: 1,
  b: 2,
  c: 3
}
let arr = ['a']
let obj1 = getMapObj(obj, arr)
console.log('obj1', obj1);

阅读 2.2k
3 个回答

你不是已经定义了是Record<string, any>吗?
还是说,你想要JSON解析并运算后的类型?那你要先写出JSON的类型呀,如果连你都不知道JSON的类型,又怎么能指望程序知道呢?

不好意思啊,功底有限,写了一下,如有不对请指正。

function getMapObj<T extends Record<string, unknown>, P extends keyof T>(
    originObj: T,
    keyArr: P[],
): { [key in P]: T[P] } {
    // let originObj = JSON.parse(JSON.stringify(originObj))
    const obj = {} as { [key in P]: T[P] };
    keyArr = keyArr.filter(Boolean);
    Object.keys(originObj)
        .filter(v => keyArr.includes(v as P))
        .forEach(v => {
            obj[v] = originObj[v];
        });
    return obj;
}
const obj = {
    a: 1,
    b: 2,
    c: 3,
};
const arr: (keyof typeof obj)[] = ['a'];

type Obj = typeof obj;

const obj1 = getMapObj<Obj, keyof Obj>(obj, arr);
console.log('obj1', obj1);
type PickByKeyList<T, KS extends (keyof T)[]> = {
    [K in KS[number]]: K extends keyof T ? T[K] : never
}

function getMapObj<T, K extends keyof T>(originObj: T, keyArr: readonly K[])
    : PickByKeyList<T, K[]> {
    // let originObj = JSON.parse(JSON.stringify(originObj))
    return Object.fromEntries(
        Object.entries(originObj).filter(([key]) => keyArr.includes(key as K))
    ) as PickByKeyList<T, K[]>;
}

let obj = {
    a: 1,
    b: 2,
    c: 3
}

const arr = ['a'] as const;     // 这里 arr 必须声明为 as const

let obj1 = getMapObj(obj, arr)
console.log('obj1', obj1);

image.png

注意 arr 必须是一个类型固定的变量,只有类型固定才可能在编译期识别出来。如果类型不固定,getMapObj 就只能返回 Partial<T>,将所有属性都声明为可选的,但具体有哪些只有运行时才知道(静态类型分析不出来)

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题