Здесь новичок в TypeScript, а сейчас я изучаю язык на Здесь. В настоящее время мне трудно понять разницу между этими двумя частями кода.
interface Person{
age: number;
}
interface Musician extends Person{
instrument: string;
}
var drummer:Musician = {
instrument: "drum",
age: 28
}
а также
interface Person{
age: number;
}
interface Musician extends Person{
instrument: string;
}
var drummer = <Musician>{}
drummer.instrument = "drum"
drummer.age = 28
Какая разница между двумя? и есть ли конкретная ситуация, когда лучше использовать первую / вторую реализацию?
Спасибо.





Примеры несколько отличаются:
Musician, а затем назначаете объект той переменной, которая соответствует этому типу.Musicican.
{} as Musician - синтаксис угловых скобок, который вы используете, несовместим с расширением синтаксиса JSX, обычно используемым в приложениях React, поэтому он был заменен чем-то менее двусмысленным.Я бы порекомендовал первый пример второму в подавляющем большинстве случаев - пустой объект на самом деле не реализует Musician, так что вы эффективно обходите здесь проверку типов!
Один сценарий, в котором вы могли бы обосновать использование второго метода, был бы, если у вас есть Musician, который запускается пустым и заполняется позже - в этом случае, однако, я думаю, вам лучше смоделировать это с помощью определения типа сам, сделав поля необязательными:
interface Person {
// '?' makes a field optional
age?: number;
}
interface Musician extends Person {
instrument?: string;
}
// The cast can now be replaced with a proper type
var drummer: Musician = {};
drummer.instrument = "drum";
drummer.age = 28;
Это проясняет (как для вас, так и для других разработчиков и компилятора), что есть случаи, когда эти поля не будут определены.
В конечном итоге они сводятся к одному и тому же, но по возможности предпочтительнее первое.
В таком случае:
var drummer: Musician = {
instrument: "drum",
age: 28
}
вы объявляете drummer как Musician, используя аннотация типа и присваивая ему литерал объекта. Компилятору это нравится, потому что он может проверить, что да, литерал объекта, который вы назначаете, совместим с интерфейсом Musician. Он имеет свойство instrument со строковым значением и свойство age с числовым значением.
А что, если мы попробуем это:
var drummer: Musician = {};
// ~~~~~~~ <-- error!
// Type '{}' is not assignable to type 'Musician'.
// Property 'instrument' is missing in type '{}'.
drummer.instrument = "drum"
drummer.age = 28
Присвоение пустого литерала объекта значению, объявленному как Musician, вызывает ошибку компилятора. В конце концов, пустой литерал объекта не имеет свойства instrument со строковым значением или свойства age с числовым значением. И вас об этом предупреждают. Теперь ты знает, что следующие две строки исправят эту проблему, но компилятор этого не делает.
Таким образом, вы можете изменить его, чтобы использовать утверждение типа вместо аннотации типа:
var drummer = <Musician>{}; // okay
drummer.instrument = "drum"
drummer.age = 28
Утверждение - это когда вы говорите компилятору, что «этот объект действительно является Musician, хотя прямо сейчас он на него не похож». Вы берете на себя ответственность за то, чтобы drummer был Musician, и освобождаете компилятор от обязанности проверять это за вас.
А поскольку следующие две строки добавляют необходимые свойства, все в порядке.
Первое предпочтительнее, потому что вы обычно хотите, чтобы компилятор проверял ваши типы, если это возможно. Утверждение типа дает некоторую безопасность, которая хороша до тех пор, пока это не произойдет, как вождение автомобиля без ремня безопасности:
var drummer = <Musician>{}; // okay
drummer.age = 28;
// whoops, forgot the instrument, but TypeScript isn't complaining
// ... later ...
console.info(drummer.instrument.toUpperCase());
// no error at compile time
// but blows up at runtime
Бывают случаи, когда вам нужно использовать утверждения типа. Например, если у вас есть какая-то круговая ссылка, в которой вам нужно построить объект по частям:
interface MarriedPerson extends Person {
spouse: MarriedPerson
}
var adam: MarriedPerson = {
age: 0,
// spouse: eve <-- can't do this before eve is defined
} as MarriedPerson;
var eve: MarriedPerson = {
age: 0,
spouse: adam
}
adam.spouse = eve; // okay now
В приведенном выше примере каждому MarriedPerson нужна ссылка на MarriedPerson ... но ее не будет, пока вы ее не создадите. Таким образом, вы вынуждены прибегать к тому, чтобы иметь короткий период времени, когда один из объектов MarriedPerson не имеет требуемого spouse. Итак, утверждения требуются.
Имеет ли это смысл? Надеюсь, поможет; удачи!