2016-10-05 6 views
0

Скажем, у меня есть объект, подобный следующему, ошибки отображение имен в их код и сообщение:Как я могу определить общую структуру объекта, не добавляя ни одно из его свойств в определение?

let Errors = { FOO: [1, 'Foo error'], BAR: [2, 'Bar error'], BAZ: [3, 'Baz error'] }

Каждое свойство имеет выведенный тип (number | string)[], хорошо, но мы знаем, что тип на самом деле более конкретно [number, string]. Для того, чтобы позволить машинопись знать об этом, насколько я понимаю, что мы должны сделать что-то вроде следующего:

let Errors = { FOO: [1, 'Foo error'] as [number, string], BAR: [2, 'Bar error'] as [number, string], BAZ: [3, 'Baz error'] as [number, string] }

Можно ли добавить соответствующие типы всех свойств в более чистой образом, избегает всех этих повторений?

+0

Если вы используете это определение, вам необходимо получить доступ к этому объекту как Obj ['prop']. Указанный интерфейс указывает, что объект является индексируемым, и этот результат «число». Я могу ошибаться, но я не думаю, что можно указать это объявление типа, позволяющее любому свойству иметь определенный номер, возможно, используя прокси. Вы всегда можете использовать 'any' – Paarth

+0

Доступ к объектам Obj с использованием этих обозначений считается неправильной практикой, когда вы знаете имя свойства во время разработки. А также я могу писать любые строки таким образом, чтобы TS не жаловался на это, бессмысленно. –

+3

Ну что вы хотите? Вы хотите, чтобы TS мог рассказать вам, когда вы пропустили свойство (например, «Obj.prob»)? Когда вы пропустили требуемую собственность? Если вы хотите использовать произвольные свойства, зачем вообще вводить их? – jonrsharpe

ответ

2

Невозможно сообщить компилятору, что все свойства имеют один и тот же тип.

Вы можете использовать type alias, чтобы сделать его немного лучше:

type ErrorInfo = [number, string]; 

let Errors = { 
    FOO: [1, 'Foo error'] as ErrorInfo, 
    BAR: [2, 'Bar error'] as ErrorInfo, 
    BAZ: [3, 'Baz error'] as ErrorInfo 
}; 

Другой вариант должен иметь тип для вашего Errors:

type ErrorInfo = [number, string]; 

interface ErrorMap = { 
    FOO: ErrorInfo; 
    BAR: ErrorInfo; 
    BAZ: ErrorInfo; 
} 

let Errors: ErrorMap = { 
    FOO: [1, 'Foo error'], 
    BAR: [2, 'Bar error'], 
    BAZ: [3, 'Baz error'] 
}; 

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