Issue
Okay, so I have a system where I use attributes in the form of symbols.
const A = Symbol.for(":a")
const B = Symbol.for(":b")
const C = Symbol.for(":c")
interface Attributes {
[A]: string
[B]: number
[C]: boolean
}
const pattern_1 = [A, B]
const pattern_2 = [B, C]
I need a function that can infer the object type:
{ [A]: string, [B]: number }
frompattern_1
[A, B]
{ [B]: number, [C]: boolean }
frompattern_2
[B, C]
I have gotten this far
type AttributeKeys ReadonlyArray<keyof Attributes>
declare function pattern<Pattern extends AttributeKeys>(...attrs: Pattern): Pattern
const PATTERN = pattern(A, B) // inferred type is [typeof A, typeof B]
What I cannot do, is to change the tuple type into an object. In the next step I want it to infer that I will return a an object with the keys from the array as keys in a new object type. I want the type of the keys to match that which is declared in Attributes. This is the farthest I've been able to come:
declare function pull1<T>(pattern: T): { [K in keyof T]: K extends keyof Attributes ? Attributes[K] : never }
const entity1 = pull1(PATTERN) // inferred type is [never, never]
declare function pull2<T>(pattern: T): { [K in keyof Attributes]: K extends T ? Attributes[K] : never }
const entity2 = pull2(PATTERN) // inferred type is { [A]: never, [B]: never, [C]: never }
I cannot get this to work, need help! Here's a TypeScript playground link if any one think they can crack it.
PS. I have to use symbols but the rest is just things I've tried. If there's a better way please share!
Solution
You can just use the Pick
predefined mapped types:
declare function pull2<T extends Array<keyof Attributes>>(pattern: T): Pick<Attributes, T[number]>
const entity2 = pull2(PATTERN)
let a = entity2[A] // string
let b = entity2[B] // number
entity2[C] // err
Answered By - Titian Cernicova-Dragomir
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.