Как установить дополнительные параметры класса в Angular 2- Typescript?
Я знаю, что в Typescript необязательных параметры могут быть отмечены знаком вопросительного знака.
Однако, единственный способ найти экземпляр класса с ключевым словом new.
Дело в том, что на основе классов Angular 2 стартера "герой" учебники не, созданных с помощью нового ключевого слова, и насколько я понял, что внутренне сделано Angular.
Например, у меня есть этот код:
модели /users.ts
export class User {
id: number;
name: string; // I want this to be optional
}
модель/макетный users.ts
import {User} from './user';
export var USERS: User[] = [
{
id: 1
// no name (I wanted it to be optional for user with id 1)
},
{
id: 2,
name: "User 2"
},
]
услуги /user.service.ts
import {Injectable} from 'angular2/core';
import {USERS} from './../models/mock-users';
@Injectable()
export class UserService {
getUsers() {
return Promise.resolve(USERS);
}
}
мнение/мой-component.component.ts
// imports here...
@Component({
// ...
})
export class MyComponent {
constructor(private _userService: UserService) { }
getUsers() {
this._userService.getUsers().then(users => console.log(users));
}
}
Ответы
Ответ 1
В вашем случае было бы удобнее использовать интерфейс для пользователя.
export interface User {
id: number;
name?: string; // interfaces allow fields to be optional
}
Я использую интерфейсы, когда хочу определить "фигуру" объекта, классы, когда мне нужно добавить поведение (методы). Если вам нужно только перемещать данные, я бы использовал интерфейс.
Если вам нужен класс, то синтаксис для создания экземпляров Users в mock-users.ts
должен быть немного другим. Во-первых, нет "дополнительных полей класса" в TypeScript. Любое поле не может быть установлено /'undefined', поэтому не имеет смысла отметить поле необязательным. Вы можете создать экземпляр класса с ключевым словом new
- недостатком является то, что вам нужно написать конструктор для установки значений полей или присвоить экземпляр переменной и задать поля. Но нет ничего плохого в использовании нового ключевого слова, особенно для тестовых объектов.
Вы также можете создать экземпляр объекта с литералом объекта, как вы это делали в mock-users.ts
- вам нужно быть более явным, добавив приведение.
export var USERS: User[] = [
<User> { // explicit cast to let the TypeScript compiler know you know what you're doing
id: 1
// no name (I wanted it to be optional for user with id 1)
},
{
id: 2,
name: "User 2"
},
]
Без трансляции компилятор TypeScript выдаст ошибку. Это по дизайну, чтобы поймать ошибки. Если вы хотите узнать больше о (интересных) причинах, здесь приведено подробное обсуждение некоторых соображений, лежащих в основе проверки типов:
Ответ 2
class User {
constructor(public id: number, public name: string = null) {}
}
var USERS: User[] = [
new User(1),
new User(2, 'User 2')
];
console.log(USERS);
JsFiddle
Использование конструктора, вероятно, сделает вашу жизнь намного проще. Вы не получите undefined
при попытке получить имя пользователя, и вы сможете определять функции в классе. Единственное различие заключается в том, что вы использовали бы new User(...)
вместо того, чтобы просто использовать литерал объекта как тип.
Ответ 3
Другим способом является использование Object.assign
для расширения допустимого типизированного объекта с помощью свойства, которое вам нужно (опускание свойства a
и c
в этом примере)
export class A {
a:number=1;
b:number;
c:string;
d:string;
}
let validA:A = Object.assign(new A(),{
b:3,
d:'Lorem ipsum'
});
Я лично предпочитаю этот синтаксис, чтобы избежать многострочной инициализации объекта и скучной вещи для создания интерфейса (так что другой файл совершенно бесполезен, если существует подходящий класс) для каждой модели моего приложения.
Кроме того, не стесняйтесь устанавливать значение по умолчанию в определении вашего класса, даже если оно не является обязательным для этого случая.
Последнее важное обстоятельство заключается в том, что вы не теряете методы класса в этом случае (противопоставляя {} casting)