Примечание: я предполагаю, что вы используете версию TypeScript 3.5 или новее; в TypeScript 3.5 было внесено изменение, так что параметры типа generi c неявно ограничены unknown
вместо пустого типа объекта {}
, а также некоторые незначительные детали о различиях между funcA()
и funcB()
изменено. Я не хочу делать длинный пост еще более длинным, говоря о том, как все было в TS3.4 и ниже.
Если вы явно не ограничиваете a generi c type через extends XXX
, тогда он будет неявно ограничен unknown
, «верхним типом», которому могут быть присвоены все типы. Таким образом, на практике это означает, что T
в funcA<T>()
может быть абсолютно любого типа, который вы хотите.
С другой стороны, тип пустого объекта {}
- это тип, для которого почти все типы могут быть присвоены, кроме для null
и undefined
, когда вы включили параметр компилятора --strictNullChecks
(что вам следует) . Даже примитивные типы, такие как string
и number
, могут быть присвоены {}
.
Итак, сравните:
function funcA<T>() { }
funcA<undefined>(); // okay
funcA<null>(); // okay
funcA<string>(); // okay
funcA<{ a: string }>(); // okay
с
function funcB<T extends {}>() { }
funcB<undefined>(); // error
funcB<null>(); // error
funcB<string>(); // okay
funcB<{ a: string }>(); // okay
Единственная разница в что T extends {}
запрещает null
и undefined
.
Это может немного сбивать с толку, что {}
, так называемый "объектный" тип, будет принимать примитивы вроде string
и number
. Это помогает думать о таких окруженных фигурными скобками типах, как {}
и {a: string}
, а также обо всех типах interface
не обязательно как о «истинных» типах объектов, но как о типах значений, в которые вы можете индексировать их, как если бы они были объектами без ошибок времени выполнения. Примитивы, за исключением null
и undefined
, «объектно-подобны» в том смысле, что вы можете обращаться с ними, как если бы они были обернуты их эквивалентами объекта :
const s: string = "";
s.toUpperCase(); // okay
И поэтому даже примитивы, такие как string
, могут быть присвоены типам, заключенным в фигурные скобки, если члены этих типов совпадают:
const x: { length: number } = s; // okay
Если вам действительно нужен express тип, который принимает только «true», например, не примитивные объекты, вы можете использовать object
:
const y: object & { length: number } = s; // error
const z: object & { length: number } = { length: 10 }; // okay
Но я (серьезно) отклоняюсь.
Хорошо, надеюсь, что это поможет; удачи!
Детская площадка ссылка на код