@Scorpiored88

Почему ругается компилятор typescript?

Всем доброго!
Вот решил познакомится с Angular 2 (+ заодно и typescript с es6).
Пока только вникаю... вот мой фрагмент кода :

export class AppComponent {
   title = 'hero';
    hero: Hero = {
      id: 1,
      name: 'Wind'
    }

 }

запускаю проект командами :
tsc && concurrently \"tsc -w\" \"lite-server\"

Все билдится,все ок...
в процессе изменил код на :
export class AppComponent {
  constructor (){
    this.sommm = 'from this some'
  }
    title = 'hero';
    hero: Hero = {
      id: 1,
      name: 'Wind'
    }
 }


тоесть добавил
constructor (){
    this.sommm = 'from this some'
  }

все также работает, и переменная sommm в html как {{somme}} отображается нормально.Но вот как только я перезапускаю сервер,вновь компиляция не проходит, говорит :

tsc && concurrently "tsc -w" "lite-server"

app/app.component.ts(15,10): error TS2339: Property 'sommm' does not exist on type 'AppComponent'.

npm ERR! Darwin 15.5.0
npm ERR! argv "/Users/scorpio/.nvm/versions/node/v5.1.0/bin/node" "/Users/scorpio/.nvm/versions/node/v5.1.0/bin/npm" "start"
npm ERR! node v5.1.0
npm ERR! npm v3.3.12
npm ERR! code ELIFECYCLE
npm ERR! angular2-quickstart@1.0.0 start: `tsc && concurrently "tsc -w" "lite-server" `
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the angular2-quickstart@1.0.0 start script 'tsc && concurrently "tsc -w" "lite-server" '.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the angular2-quickstart package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! tsc && concurrently "tsc -w" "lite-server"
npm ERR! You can get their info via:
npm ERR! npm owner ls angular2-quickstart
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR! /Users/scorpio/Documents/git/io2/heroes/npm-debug.log



Пожалуйста объясните мне что происходит и почему. Спасибо за понимание :)

P.S.
Может это потому что constructor запускается при создании через new ?
  • Вопрос задан
  • 1566 просмотров
Решения вопроса 1
@bromzh
Drugs-driven development
Немного поправлю Евгения, достаточно объявить нужное поле в классе, тип можно не ставить:
export class AppComponent {
    sommm; // Можно и без типа, зависит от настройки компилятора
    title = 'hero';
    hero: Hero = {
      id: 1,
      name: 'Wind'
    }
    constructor (){
      this.sommm = 'from this some'
    }    
 }


Или ещё можно добавить модификатор в аргумент конструктора:
export class AppComponent {
    // В Angular 2 так можно делать в классах, 
    // которые не являются компонентами/директивами/сервисами/пайпами и т.п.
    constructor (public sommm: string = 'from this some') {}   
 }
// Это аналогично такому:
export class AppComponent {
    sommm: string;
    constructor (sommm: string = 'from this some') {
        this.sommm = sommm;
    }    
 }

Но типы всё-таки лучше указывать.

UPD 0. В TypeScript обычно, если переменная имеет тип, отличный от any, то динамически добавлять поля в неё нельзя. Когда создаётся экземпляр класса (оператор new), вызывается специальный метод с именем 'constructor'. Ты пытаешься в конструкторе записать в поле sommm. Компилятор TypeScript работает до рантайма и типы определяет исходя из объявления класса. В данном случае, тип AppComponent имеет 2 поля (title, hero). Так что с его точки зрения, у типа AppComponent нет поля sommm, потому-то он и ругается.
Иногда, видимо из-за особенностей лайв-серверов, бывает, что хоть компилятор и ругается на несоответствие типов, но код запускается и работает, ведь с точки зрения JS, всё выглядит верно.

UPD 1. Хоть я и привёл пример, где не указывал типы переменных, но так делать не стоит (почти) никогда. Чтобы оградить себя от написания такого кода, можно добавить опцию компилятора "noImplicitAny". Без неё следующий код скомпилируется без ошибок:
let a;
function foo(bar) {}
class Bar {
  foo;
  private bar;
}

Со включённой опцией компилятор выдаст ошибки там, где переменные, аргументы функций и методов или поля классов объявлены без типов.
Нужно всегда стараться указывать тип у переменных. Если один тип не подходит, можно попробовать сделать функцию/метод/класс дженериками. Если тип неизвестен - то можно поставить any. Но обычно такое бывает редко, ведь обычно ты знаешь, что за тип ожидается (у меня в проектах практически нет переменных с типом any).

UPD 2. Я привёл пример, где в конструкторе указывается модификатор. Это специальный синтаксис в Typescript, который позволяет уменьшить количество повторяющегося кода.
Однако, есть важный момент: внедрение зависимостей в компоненты/директивы/сервисы/и т.п. во втором ангуляре идёт через конструктор. Причём, в typescript-версии, фреймворк по-умолчанию извлекает информацию о типе аргумента конструктора и пытается внедрить по этому типу нужную зависимость. Поэтому в конструкторах должны быть только внедряемые зависимости.

UPD 3. Если пишешь на ангуляре, то стоит изучить styleguide и стараться следовать ему. Плюс, хорошо ещё прикрутить к проекту tslint.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
AppFA
@AppFA
Frontend developer at Yandex
Попробуйте объявить тип этой переменной до конструктора
У вас в ошибке сказано, что нету такого свойства у класса:
"Property 'sommm' does not exist on type 'AppComponent'."
sommm: string;

constructor() {
    this.sommm = 'from this some';
}
Ответ написан
AMar4enko
@AMar4enko
public somm;
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы