I currently have an interface using a data member of an array of some other interface type, which can be determined by an enum:
enum E { a, b, c }
interface E2Data {
[E.a]: { a: string },
[E.b]: { b: string },
[E.c]: { c: string }
}
interface A<T extends E[] = E[]> {
data: { [i in keyof T]: T[i] extends E ? E2Data[T[i]] : never }
}
// Can give the enums in the template, and get autocomplete in the data.
let a1: A<[E.a, E.b]> = {
data: [{ a: "" }, { b: "" }]
};
// Or can get autocomplete with type assertion on elements.
// Ideally this would infer template types too, but apparently not.
let a2: A = {
data: [ <E2Data[E.a]>{ a: "" }, <E2Data[E.b]>{ b: "" } ]
}
According to my understanding, I can now use a1.data and a2.data as arrays, but a1.data knows the type of each element (so actually a tuple?)
Now I want to use a 2D array for interface A's data.
I thought the below would work, but it would not allow me to index E2Data using T[i][j].
interface B<T extends E[][] = E[][]> {
data: {
[i in keyof T]:
T[i] extends E[] ? {
[j in keyof T[i]]:
T[i][j] extends E ? E2Data[T[i][j]] : never }
// ^^^^^^^^^^^^^^^
// Type 'T[i][j]' cannot be used to index type 'E2Data'.
: never
}
}
My current workaround is to use a type union, but this won't let me specify the data I want using a template.
interface B {
data: (E2Data[E.a] | E2Data[E.b] | E2Data[E.c])[][];
}
Is there a way to support the 2 methods of autocomplete on data as described above for a 2D array?
let b1: A<[ [E.a], [E.b] ]> = {
data: [ [{ a: "" }], [{ b: "" }] ]
}
let b2: A = {
data: [ [<E2Data[E.a]>{ a: "" }], [ <E2Data[E.b]>{ b: "" }] ]
}
E2Data[T[i]]withE2Data[T[i]][]in interface A. But I suspect you need to mix types or else you wouldn't have posted this.interface B. Your answer below covered that anyway!