类
const name = 'Joe';
enum Color { 'Yellow' = 1, 'Red' }
const bgColor = Color.Red;
function Demo(k: {}) {
return 'ok';
}
const someValue: {} = 'This is a string .';
const strLength = (someValue as string).length;
// const length: number = (<string> someValue).length;
const obj = {
a: 'ok',
b: 23,
c: []
};
// 解构后变量的类型
const { a: first, b: second }: { a: string, b: number } = obj;
const baz = {
test() {
console.log(this.name);
},
name: 'Joe'
};
baz.test();
const bar = { ...baz };
console.log('---------');
bar.test();
// class Foo {
// constructor() {
// this.p = 12;
// }
// m() {
// return this.p;
// }
// }
// const f = new Foo();
// console.log(f.m())
// const b = { ...f };
// console.log(b.p);
class Foo {
x: number;
constructor() {
this.x = 12;
}
}
console.log(new Foo());
class Greeting {
greeting: string;
constructor(greeting: string) {
this.greeting = greeting;
}
greet() {
return `Hello ${this.greeting}`;
}
}
const greeting = new Greeting('Joe');
console.log(greeting.greet());
// 类继承
class Animal {
// 当成员被标记成private时,它就不能在声明它的类的外部访问
// private name: string;
public name: string;
public constructor(theName: string) {
this.name = theName;
}
public move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}`);
}
}
class Snake extends Animal {
constructor(theName: string) {
super(theName);
}
move(distanceInMeters: number = 5) {
console.log('Slithering...');
super.move(distanceInMeters);
}
}
class Horse extends Animal {
constructor(theName: string) {
super(theName);
}
move(distanceInMeters: number = 10) {
super.move(distanceInMeters);
}
}
const snake = new Snake('Smith');
const tom: Animal = new Horse('Tom');
snake.move();
tom.move();
console.log(snake.name);
// 比较带有private或protected成员的类型的时候,情况就不同了。
// 如果其中一个类型里包含一个 private成员,那么只有当另外一个类型中也存在这样一个private成员,
// 并且它们都是来自同一处声明时,我们才认为这两个类型是兼容的。 对于 protected成员也使用这个规则
class Animal0 {
private name: string;
constructor(theName: string) {
this.name = theName;
}
}
class Rhino extends Animal0 {
constructor(theName: string) {
super(theName);
}
}
class Employee {
private name: string;
constructor(theName: string) {
this.name = theName;
}
}
let animal = new Animal0('Goat');
let rhino = new Rhino('Test');
let employee = new Employee('Bob');
animal = rhino;
rhino = animal;
// 私有属性在类外不能访问
// animal.name;
// 报错 Error: Animal and Employee are not compatible
// animal = employee;
console.log(employee);
// protected 与 private类似,不同在于protected修饰的成员在派生类中可以被访问
class Person {
protected name: string;
public constructor(theName: string) {
this.name = theName;
}
}
class Employee0 extends Person {
private department: string;
public constructor(theName: string, department: string) {
super(theName);
this.department = department;
}
public getElevatorPitch() {
// 在派生类中仍然可以访问基类得protected成员
console.log(`Hello I am ${this.name}, I am work in ${this.department}`);
}
}
const employee0 = new Employee0('Haward', 'New York');
employee0.getElevatorPitch();
// 类外边不能访问protected修饰的类成员
// employee0.name;
// 构造函数也可以被标记成protected。 这意味着这个类不能在包含它的类外被实例化,但是能被继承
class Folks {
protected name: string;
protected constructor(theName: string) {
this.name = theName;
}
}
class Coder extends Folks {
private department: string;
public constructor(theName: string, department: string) {
super(theName);
this.department = department;
}
public getElevatorPitch() {
console.log(`I am ${this.name}, I am working in ${this.department}`);
}
}
const coder = new Coder('Joe', 'Chengdu');
coder.getElevatorPitch();
// protected修饰的构造函数不能在类之外直接被实例化
// const folks = new Folks('Dennis');
// readonly 修饰符修饰的字段只能在声明或者构造函数中初始化
// class Octopus {
// readonly name: string;
// readonly numberOfLegs: number = 10;
// constructor(theName: string) {
// this.name = theName;
// }
// }
// 参数属性
// 给构造函数参数添加一个访问限定符来声明
// 参数属性会声明并初始化一个属性成员
class Octopus {
// private readonly name: string;
readonly numberOfLegs: number = 10;
constructor(public readonly name: string = 'I am default') {
// this.name = theName;
}
}
const octopus = new Octopus('Man with the 8 strong legs');
console.log(octopus.name);
// error! name is readonly.
// octopus.name = 'kkk';
const passcode = 'Joe`s psw';
class FontEndCoder {
private _fullName: string;
get fullName(): string {
return this._fullName;
}
set fullName(newName: string) {
if (passcode && passcode === 'Joe`s psw') {
this._fullName = newName;
} else {
console.log('Error: Unauthorized update of coder!');
}
}
}
const fontendCoder = new FontEndCoder();
fontendCoder.fullName = 'Dennis...';
if (fontendCoder.fullName) {
console.log(fontendCoder.fullName);
}
class Grid {
// 静态属性
static origin = { x: 0, y: 0 };
public calculateDistanceFromOrigin(point: { x: number, y: number }) {
const xDist = point.x - Grid.origin.x;
const yDist = point.y - Grid.origin.y;
const dis = Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
return dis;
}
constructor(public scale: number = 1) { }
}
const grid1 = new Grid(4);
const grid2 = new Grid();
console.log(grid1.calculateDistanceFromOrigin({ x: 10, y: 20 }));
console.log(grid2.calculateDistanceFromOrigin({ x: 3, y: 4 }));
// 抽象类
// 抽象类不能被实例化
// 抽象类用abstract关键之修饰,抽象类与接口的不同在于,抽象类可以包含方法的实现,抽象方法只能包含签名,且必须在派生类中实现。
// abstract class AnimalAbstact {
// abstract makeSound(): void;
// move(): void{
// console.log('roaming the earch...');
// }
// }
abstract class Human {
static legs: number = 2;
constructor(protected name: string = '') { }
abstract learn(): void;
}
class Chinese extends Human {
constructor(theName: string) {
super(theName);
}
learn(): void {
console.log('I can learn Chinese...');
}
run() {
console.log(`I can run with ${Human.legs} legs.`);
}
}
const Joe = new Chinese('Joe');
Joe.learn();
Joe.run();