TypeScript: проблема с вводом текста «A расширяет B» - PullRequest
1 голос
/ 08 мая 2020

[Править - заключительное замечание]: Оказалось, что приведенный ниже вопрос был в основном результатом некоторых неоптимальных типизаций, и обычно у вас может не быть таких проблем, как у меня в моей программе => теперь, зная это, мой вопрос похоже, больше не имеет особого смысла (как уже упоминалось ниже).


Пожалуйста, взгляните на следующий фрагмент кода TypeScript. Как B extends A эта строка c: 8, конечно, разрешена. Как мне изменить типы function f, чтобы запретить другие ключи рядом с a и b?

type A = { a: number, b: number }

function f<B extends A>(b: B): void {
}

f({
  a: 3,
  b: 4,
  c: 8 // <- This shall cause a compile error
})

" Demo

PS : Конечно, function f(b: A) {} - это не то, что я ищу. Этот пример здесь просто упрощен, реальный вариант использования намного сложнее ... важно, чтобы function f оставался общим c.


[Edit]: Поскольку мое упрощение выше вызвало некоторую путаницу: пожалуйста, найдите здесь более сложный пример, где ответ на мой вопрос выше может помочь (воображаемый API компонента пользовательского интерфейса):

Пожалуйста, имейте посмотрите на ошибку типа в Demo-A. Это должно быть исправлено в Demo-B.

Demo-A (с ошибкой типа)

Demo -B (без ошибки типа)

Но, как вы можете видеть в Demo-B, теперь вы можете добавлять недопустимые параметры в конфигурацию компонента - что не очень хорошо ... и поэтому я спросил вопрос выше.

[Изменить - позже] Не ответ на мой вопрос выше, но, по крайней мере, следующее изменение установка Demo-B должна работать должным образом: Demo- C

1 Ответ

2 голосов
/ 09 мая 2020

Это поведение является преднамеренным. TS - это язык структурных типов, в котором совместимость типов основана на подписке на подтипы, другими словами, каждый тип, имеющий все ограничения, будет соответствовать правилу. В вашем примере тип значения имеет все необходимые поля, поэтому 'a' и 'b', поэтому все в порядке.

Нет причин, по которым вы не должны разрешать передачу такого объекта в качестве дополнительных полей внутри не должно иметь значения. Сказать, что вы расширяете, означает сказать, что вам разрешено иметь больше полей в терминах композитов, таких как объекты.

Дополнительно, если вам нужен подтип, но с точными полями единственный тип, который соответствует вашим потребностям, к сожалению, будет A , поэтому подпись функции должна быть f(a: A).

И чтобы было ясно, даже с f(a: A) вы сможете передавать значения с дополнительными полями, только литералы объектов будут проверяться строго. Любое присвоенное значение с большим количеством полей может использоваться без жалоб компилятора. И причину я уже описываю.

...