简体   繁体   English

Generics 上的“keyof typeof”

[英]"keyof typeof" on Generics

Hello I have some struggle with my generic typing.您好,我的通用打字有些困难。

interface ReturnValue {
    keyA: string,
    keyB: string
}


interface FilterA {
    keyA: boolean;
}

interface FilterB {
    keyB: boolean;
}


const func = function<T>(args: T) : Pick<ReturnValue, keyof typeof args> {
    const res :Pick<ReturnValue, keyof typeof T> = {};
    Object.keys(args).map(key => {
        res[key] = key
    }) 

    return res;
}

console.log(func({keyB: true}).keyB); // should work
console.log(func({keyA: true}).keyA); // should work

console.log(func({keyA: true}).keyB); // should not work
console.log(func({keyC: true}).keyC); // should not work

But I have this error:但我有这个错误:

Type 'keyof T' does not satisfy the constraint 'keyof ReturnValue'.
  Type 'string | number | symbol' is not assignable to type 'keyof ReturnValue'.
    Type 'string' is not assignable to type 'keyof ReturnValue'.
      Type 'keyof T' is not assignable to type '"keyB"'.
        Type 'string | number | symbol' is not assignable to type '"keyB"'.
          Type 'string' is not assignable to type '"keyB"'.(2344)

Any ideas?有任何想法吗?

When I'm using the function call it's working fine, I can access only to what I gave as arguments but TS still display this error.当我使用 function 调用它工作正常时,我只能访问我作为 arguments 提供的内容,但 TS 仍然显示此错误。

The context is GraphQl.上下文是 GraphQl。 My input is an object where value of each keys is true or false .我的输入是 object ,其中每个键的值为truefalse From this object I'll build a GQL string query, fetch to api, and the return will have the same structure but value wont be boolean but string for example.从这个 object 我将构建一个 GQL 字符串查询,获取到 api,返回将具有相同的结构,但值不会是boolean ,而是string

TS Playground TS游乐场

It wort using Array.prototype.reduce and mapped types here:它在这里使用Array.prototype.reduce映射类型



interface FilterA {
    keyA: boolean;
}

interface FilterB {
    keyB: boolean;
}

type Filters = FilterA | FilterB

type Reduce<Obj> = {
    [Prop in keyof Obj]: Prop
}

const func = <Obj extends Filters>(args: Obj) =>
    Object.keys(args).reduce((acc, key) => ({
        ...acc,
        [key]: key
    }), {} as Reduce<Obj>)

func({ keyB: true }).keyB; // ok
func({ keyA: true }).keyA; // ok

func({ keyA: true }).keyB; // error
func({ keyC: true }).keyC // error

Playground操场

I have used immutable version of this approach not because it is better.我使用了这种方法的不可变版本,不是因为它更好。 I just prefer immutable data structures.我只是更喜欢不可变的数据结构。

UPDATE更新

Code example of alternative version of Reduce from comments:来自评论的替代版本的Reduce示例:

type Reduce<Obj> = {
    [Prop in keyof Obj]: Prop extends keyof ReturnValue ? ReturnValue[Prop] : never
}


interface ReturnValue {
    keyA: string,
    keyB: string
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM