Рассмотрим следующие интерфейсы:

export interface FooInterface<T, O extends FooOptions<T>> {
  items: T[];
  options: O;
}

interface FooOptions<T> {
  doSomething: (e: T) => void;
}

Теперь, когда мне нужно что-то сделать с этим, мне нужно повторить Т. Например:

const t: FooInterface<string, FooOptions<string>> = {
  items: ["a","b","c"],
  options: {doSomething: (e) => {
      console.log(e);
  }}
}

Теперь, повторяя скучно, возможно ли создать тип или интерфейс, где T должен быть строкой для обоих типов, или как-то переопределить интерфейсы, чтобы я написал вместо этого что-то вроде этого:

const t: FooInterfaceString
//or
const t: FooInterfaceOfType<string>
0
MrMamen 2 Май 2019 в 14:44

3 ответа

Лучший ответ

Другие ответы здесь верны, но я хочу добавить, что вы можете рассмотреть возможность использования значения по умолчанию для общих параметров, если вы обычно (но не всегда) просто передаете FooOptions<T> в качестве типа O:

interface FooOptions<T> {
    doSomething: (e: T) => void;
}

// note how O has a default value now
export interface FooInterface<T, O extends FooOptions<T> = FooOptions<T>> {
    items: T[];
    options: O;
}

Это позволяет вам просто пропустить параметр O, если вы хотите, чтобы он был просто FooOptions<T>:

const t: FooInterface<string> = {
    items: ["a", "b", "c"],
    options: {
        doSomething: (e) => {
            console.log(e);
        }
    }
}

И в случае, если вы действительно хотите, чтобы O был более конкретным, чем FooOptions<T> (именно поэтому у вас есть его как отдельный параметр, верно?), Вы все равно можете сделать это:

interface MoreOptions {
    doSomething: (e: string) => void;
    doNothing: () => void;
}

const u: FooInterface<string, MoreOptions> = {
    items: ["d", "e", "f"],
    options: {
        doSomething(e) { console.log(e); },
        doNothing() { console.log("lol nvm"); }
    }
}

Да, и если T обычно будет string, то вы также можете добавить для него значение по умолчанию, а затем FooInterface без параметров будет интерпретировано как FooInterface<string, FooOptions<string>>:

export interface FooInterface<T = string, O extends FooOptions<T> = FooOptions<T>> {
    items: T[];
    options: O;
}

const t: FooInterface = {
    items: ["a", "b", "c"],
    options: {
        doSomething: (e) => {
            console.log(e);
        }
    }
}

Хорошо, надеюсь, что это поможет. Удачи!

2
jcalz 2 Май 2019 в 12:18

Вы можете использовать псевдоним TypeScript:

// Declaration
type FooInterfaceOfType<T> = FooInterface<T, FooOptions<T>>;

// Usage
const t: FooInterfaceOfType<string>;
1
Emaro 2 Май 2019 в 11:49

Как насчет :

type FooInterfaceString = FooInterface<string, FooOptions<string>>;

Также, возможно, подумайте об этом, если он подходит вашему дизайну:

export interface FooInterface<T> {
  items: T[];
  options: FooOptions<T>;
}
type FooInterfaceString = FooInterface<string>;
2
Romain 2 Май 2019 в 11:46