Страницы

Поиск по вопросам

среда, 19 июня 2019 г.

TypeScript, почему работает var v: Object = {name1: 'val1'}

Приветствую! Имеем TypeScript 1.8
Пишу так:
var v: Object; v = {name1: 'val1'}
Все хорошо компилируется. Вроде как Object совместим с любым объектом. Пишу вот так:
interface MyInterface { name2: string; } var v: MyInterface; v = {name1: 'val1', name2: 'val2'} // <--- РУГАЕТСЯ
И он ругается: Error:(138, 55) TS2322: Type '{ name1: 'val1', name2: 'val2' }' is not assignable to type 'MyInterface '. Object literal may only specify known properties, and 'name1' does not exist in type 'MyInterface '.
НО! Если только "known properties", то почему не ругается на первый вариант с Object? Ведь в lib.d.ts Object также определен как Interface:
interface Object {...
И, естественно, никакого name1 там также не описано.


Ответ

Окей, вопрос оказался сложнее. Заглядываем в спецификацию языка, раздел 3.11.5. Читаем:
A property P is said to be expected in a type T if one of the following is true: T is not an object, union, or intersection type. T is an object type and T has a property with the same name as P T has a string or numeric index signature, T has no properties, or T is the global type 'Object'. (***) T is a union or intersection type and P is expected in at least one of the constituent types of T
Таким образом, особое место Object'а прямо прописано в спецификации, в пункте, обозначенном тремя звёздочками. Также специально оговорен интерфейс без свойств.

Пример:
Это компилируется, потому что Object
var v: Object; v = {name1: 'val1', name2: 'val2'}
Это не компилируется из-за лишнего свойства name1
interface MyInterface1 { name2: string; }
var x1: MyInterface1; x1 = {name1: 'val1', name2: 'val2'}
Это компилируется, так как интерфейс без свойств:
interface MyInterface2 { }
var x2: MyInterface2; x2 = {name1: 'val1', name2: 'val2'}
Это не компилируется, лишнее свойство name1 и name2, исключения не применимы:
interface MyInterface3 extends Object { }
var x3: MyInterface3; x3 = {name1: 'val1', name2: 'val2'}
Это компилируется, так как есть index signature:
interface MyInterface4 { [x: string]: any; }
var x4: MyInterface4; x4 = {name1: 'val1', name2: 'val2'}

Комментариев нет:

Отправить комментарий