2016-12-15 12 views
0

Исходя из бесприбыльного языка JavaScript для типизированного TypeScript, вы начинаете использовать интерфейсы. Иногда простые вопросы о том, как структурировать приложение, превращаются в жестокие дискуссии с моими товарищами по команде :) Мы создаем приложение React + Redux + TypeScript, и у нас есть две вещи: Состояние приложения для пользователя (пользовательское представление внутри магазина Redux) и Ответ API пользователя (Описывает ответ API JSON), оба из них имеют интерфейс, который на данный момент является одним и тем же, но это может измениться. Отображение осуществляется с помощью некоторых пользовательских функций:Два отдельных интерфейса или один расширенный другим: до DRY или не к DRY

const mapUserApiToState = (user: IUserAPI): IUserState => { ... } 

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

(1) Отдельные каждый интерфейс в свой собственный файл. Но вам придется повторять одинаковые атрибуты для каждого интерфейса, который нарушает принцип DRY.

// file1.ts 
interface IUserState { 
    id: number; 
    name: string; 
    kids: number; 
} 

// file2.ts 
interface IUserAPI { 
    id: number; 
    name: string; 
    kids: number; 
} 

(2) Просто продлить один интерфейс с другим. Таким образом, вам не нужно будет повторять себя, но это будет означать, что один интерфейс расширяет другой, когда в действительности они выглядят одинаково, но для совершенно разных целей

// file1.ts 
interface IUserState { 
    id: number; 
    name: string; 
    kids: number; 
} 

// file2.ts 
interface IUserAPI extends IUser {} 

(3) Создать некоторые третьи абстрактные интерфейс. Но это создает еще один файл с интерфейсом, который не должен использоваться (где бы вы использовать IUser?)

// file1.ts 
interface IUser { 
    id: number; 
    name: string; 
    kids: number; 
} 

// file2.ts 
interface IUserState extends IUser {} 

// file3.ts 
interface IUserAPI extends IUser {} 

(4) Бросить время трать своё на тривиальные вещи. YAGNI.

+1

пару вопросов, которые я задал себе в этом случае: существуют ли два интерфейса **, вероятно, отклоняются? приложение распадается, если они не синхронизированы? Можете ли вы объединить их, а не абстрагировать их еще больше, чтобы иметь 1 интерфейс вместо двух или трех? – alebianco

+1

@mseimys В третьем случае, почему вы бы сказали, что 'IUser' не будет использоваться? Этот интерфейс уже является частью других интерфейсов «IUserState» и «IUserAPI». Не будете ли вы использовать его для хранения структурной информации для обоих производных интерфейсов? Я имею в виду, вы измените этот интерфейс, когда будут общие изменения, не так ли? – Leone

+0

@ Leone yes, я бы использовал общие свойства в этом интерфейсе «IUser», но думаю, что нецелесообразно использовать его везде, в этом случае другие два совершенно бесполезны , в первую очередь, поэтому мой вопрос :) Ну мой пример может выглядеть тривиальным, , но представьте, что у вас есть десятки сложных атрибутов, как 'points: [{isVisible: true, title:" Title ", tags: [1, 2, 3]}]' – mseimys

ответ

0

После долгих обсуждений мы решили использовать функцию Type12 typeof и решили дублировать перечисление переменных, но вместо использования двух интерфейсов мы используем значение состояния приложения по умолчанию в качестве определения для нашего типа. Таким образом, это не то же самое, что два интерфейса, но на самом деле имеет смысл.

interface IUserAPI { 
    id: number; 
    name: string; 
    kids: number; 
} 

const defaultUserState = { 
    id: 0, 
    name: "Unnamed", 
    kids: 0 
} 

type IUserState = typeof defaultUserState