#typescript
#typescript
Вопрос:
Кажется, я не могу понять, почему я не могу использовать пользовательский тип внутри интерфейса.
У меня есть следующее определение:
type Operation = 'update'|'remove'|'add'
interface Rule {
op: Operation
path:string
value?:any
}
function applyDiff<Output>(rules: Rule[], obj: object): Output;
но я получаю Type 'string' is not assignable to type 'Operation'
сообщение об ошибке при этом неудачном тестировании:
const obj = {a: {b:1, c:2}}
const rules = [
{op: 'update', path: 'a.c', value:10},
]
const result = applyDiff(rules, obj)
но этот код работает просто отлично:
function fn(x: number, y: 'add'|'remove'|'update'){
return x > 1 amp;amp; y === 'add'
}
const result = fn(1, 'remove')
Чего мне здесь не хватает? Я был бы признателен за любое полезное руководство по этому вопросу. Спасибо.
Ответ №1:
Во-первых, простое решение:
const rules: Rule[] = [
// ^------^
{op: 'update', path: 'a.c', value:10},
]
Но почему это не работает с самого начала? Потому что предполагаемый тип rules
является {op: string; path: string; value: number}[]
, и существует множество string
s, которые не являются ни одним из значений в Operation
объединении. Объекты и массивы изменяемы, поэтому ничто не мешает op
изменять значение (например, помещать новый объект в массив или изменять существующий объект в массиве) между определением rules
и передачей его applyDiff
.
Это также предлагает некоторые другие решения:
-
Передайте массив непосредственно в функцию:
const result = applyDiff([ {op: 'update', path: 'a.c', value:10}, ], obj);
Здесь значения не могут меняться между определением массива и передачей его в
applyDiff
, поэтому выводится более узкий тип{op: 'update'; path: 'a.c'; value: 10}[]
. -
Используйте
const
утверждение, чтобы явно сузить тип правила:const rules = [ {op: 'update', path: 'a.c', value:10} as const, // ^-------^ ];
Это сообщает компилятору, что вы считаете этот объект неизменяемым, что приводит его к выводу о более узком типе для
rules
тоже. Вместо этого вы могли бы явно сузить типop
:const rules = [ {op: 'update' as const, path: 'a.c', value:10}, // ^-------^ ];
с аналогичными эффектами.
Комментарии:
1. Это определенно работает, но если это правильный ответ, то это работает так, как ожидалось, и мой вопрос отчасти недействителен. Моя проблема в том, что это определение является частью библиотеки, и я тестирую то, что пользователь получает «из коробки», чего в данном случае немного. С таким же успехом я мог бы оставить
op
тип равнымstring
. Спасибо за быстрый ответ.2. Я только что увидел предложение с
const
— я искал что-то подобное. Высоко ценится.3. @DejanToteff какое определение является частью библиотеки? Похоже, что вопрос, возможно, не полностью отражал контекст.
4. часть с
appyDiff
объявлением. Но предложение сconst
работает для меня просто отлично. Я не упомянул контекст, поскольку считаю, что это не имеет отношения к делу, но я обязательно включу его в свой следующий вопрос.