Typescript 2D 가변 템플릿

Sep 25 2020

현재 열거 형으로 확인할 수있는 다른 인터페이스 유형 배열의 데이터 멤버를 사용하는 인터페이스가 있습니다.

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: "" } ]
}

내 이해에 따르면 이제 a1.data및 a2.data배열로 사용할 수 있지만 a1.data각 요소의 유형을 알고 있습니다 (실제로 튜플?)

이제interface A 의 데이터에 2D 배열을 사용하고 싶습니다 .

나는 아래 일 것이라고 생각하지만, 인덱스에 저를 허용하지 않을 E2Data사용 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
    }
}

내 현재 해결 방법은 유형 통합을 사용하는 것이지만 템플릿을 사용하여 원하는 데이터를 지정할 수는 없습니다.

interface B {
    data: (E2Data[E.a] | E2Data[E.b] | E2Data[E.c])[][];
}

data2D 배열에 대해 위에서 설명한대로 두 가지 자동 완성 방법을 지원하는 방법이 있습니까?

let b1: A<[ [E.a], [E.b] ]> = {
    data: [ [{ a: "" }], [{ b: "" }] ]
}

let b2: A = {
    data: [ [<E2Data[E.a]>{ a: "" }], [ <E2Data[E.b]>{ b: "" }] ]
}

답변

1 LindaPaiste Sep 26 2020 at 04:22

이것은 나에게 약간의 생각을 가져다 주었지만 솔루션은 이미 원본으로 대부분의 다리 작업을 수행했기 때문에 실제로 매우 간단합니다 interface A.

DataArrayE 값의 튜플을 제네릭 으로 취하고 해당 E2Data의 튜플을 반환 하는 제네릭 유형 을 정의합니다 . DataArray논리 를 포함하고 A사용 하도록 다시 형식 을 지정할 수 있지만 간단하게에서 기존 논리에 액세스 해 보겠습니다 A.

type DataArray<T extends E[]> = A<T>['data'];

에서 중첩 된 인덱스 서명을 사용하는 대신 interface B단일 인덱스 서명 DataArray을 사용하고 유형을 호출 하여 내부 배열을 만들 수 있습니다.

interface B<T extends E[][] = E[][]> {
    data: {
        [i in keyof T]: T[i] extends E[] ? DataArray<T[i]> : never
    }
}

이제 E를 혼합하고 일치시켜 2D 데이터 유형을 만듭니다.

let b: B<[[E.a], [E.b, E.c]]> = {
    data: [ [{ a: "" }], [{ b: "" }, {c: ""}] ]
}

편집 나는 당신이 이것을 요구하지 않았다는 것을 알고 있지만 여기에 더 깊게 중첩 된 값을 처리하는 방법이 있습니다. ( 재귀 배열에 대한 이 답변의 지침 포함 ).

interface Nested<T> extends Array<Nested<T> | T> {
}

type NestedData<T extends Nested<E>> = { 
    [i in keyof T]: T[i] extends E ? E2Data[T[i]] : T[i] extends Nested<E> ? NestedData<T[i]> : never
}

interface C<T extends Nested<E>> {
    data: NestedData<T>
}

let c: C<[E.a, [E.b, [E.c]]]> = {
    data: [ { a: "" }, [{ b: "" }, [{c: ""}] ]]
}