Почему подтипы необходимо присвоить переменной, прежде чем использовать в качестве аргумента функции? - PullRequest
2 голосов
/ 06 мая 2019

Я изучаю подтипы и мне интересно, почему приведенный здесь пример https://www.typescriptlang.org/docs/handbook/type-compatibility.html компилируется, но когда я передаю подтип непосредственно в качестве аргумента функции, он не компилируется.

Вот оригинальный код от typescriptlang.org

interface Named {
    name: string;
}

let x: Named;
// y's inferred type is { name: string; location: string; }
let y = { name: "Alice", location: "Seattle" };


function greet(n: Named) {
    console.log("Hello, " + n.name);
}
greet(y); // OK

Это прекрасно компилируется. Но эта версия, где подтип не назначен для y, завершается неудачей.

interface Named {
    name: string;
}

let x: Named;

function greet(n: Named) {
    console.log("Hello, " + n.name);
}
greet({ name: "Alice", location: "Seattle" }); // NOT OK

Я получаю ошибку:

Аргумент типа '{name: string; расположение: строка; } 'не может быть назначен параметру типа' Named '. Объектный литерал может указывать только известные свойства, а «location» не существует в типе «Named».

Почему подтип {имя: "Алиса", местоположение: "Сиэтл"} должен быть сначала назначен переменной?

1 Ответ

2 голосов
/ 06 мая 2019

Это потому, что когда вы используете «свежий» литерал объекта (то есть тот, который еще не был назначен переменной) в месте, которое ожидает определенного типа, часто ошибка для добавления свойствне упоминается в типе.Так что это помечается как ошибка через проверку избыточного свойства .Это одно из немногих мест, где тип рассматривается как «закрытый» или «точный» , а не «открытый».

Существуют обходные пути в том случае, если вы не имеете в виду проверку лишних свойств.Одним из них является добавление индексной подписи к типу параметра n, чтобы все дополнительные свойства были приемлемыми:

function greet(n: Named & { [x: string]: unknown }) {
  console.log("Hello, " + n.name);
}
greet({ name: "Alice", location: "Seattle" }); // okay

Или, если вы обычно хотите такую ​​проверку, но просто хотитечтобы вызвать greet() с этим литералом конкретного объекта, вы можете использовать утверждение типа , чтобы избежать промежуточных переменных:

greet({ name: "Alice", location: "Seattle" } as Named); // okay

Это ваше дело.Хорошо, надеюсь, это поможет;удачи!

...