1

I need to convert array to string union. See below

export class Foo<K extends string[]> {
    make<L extends string[]>(keys: L): Foo<L> {
        return new Foo();
    }
    get(key: K) {

    }
}

const x = Foo.make(['a', 'b'])

// need to constraint this to 'a' | 'b'
x.get('')
luky
  • 2,263
  • 3
  • 22
  • 40

1 Answers1

1

The first issue is capturing the string literals when you call make. You could do this in one of several ways. You could use tuples in rest parameters (make<L extends string[]>(...keys: L): Foo<L> but this will require you call the make function as Foo.make('a', 'b').

Another option is to use the fact that the compiler will preserve literal types if they are assigned to a type parameter constrained to string. This will preserve the current way of calling.

The issue of getting the union is simple, you can use a type query.

export class Foo<K extends string[]> {
    static make<L extends V[], V extends string>(keys: L): Foo<L> {
        return new Foo();
    }
    get(key: K[number]) { // index type

    }
}

const x = Foo.make(['a', 'b'])

x.get("a")
x.get("A") // err

Playground Link

Another option is not to use the tuple type in L, just capture the union directly when calling make:

export class Foo<K extends string> {
    static make<V extends string>(keys: V[]): Foo<V> {
        return new Foo();
    }
    get(key: K) { // index type

    }
}

const x = Foo.make(['a', 'b'])

x.get("a")
x.get("A") // err

Playground Link

Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
  • thanks it works, it is little bit tricky i have to compile the tricks in my mind :) i understand that if it is exactly string that it accepts anything, but how comes that extends string works another way. it means that it must be V a V is 'a' | 'b' but if V extends string it doesnt mean anything as well? you get my question. – luky Dec 13 '19 at 14:59
  • 1
    @luky It is just the defined compiler behavior.. before `as const` it was one of the few ways to hint to the compiler you want literal types... TS has multiple such 'constraints that hint' – Titian Cernicova-Dragomir Dec 13 '19 at 18:17