class 类(属性,方法)
public:公共的;protected:受保护的;private:私有的。
class Person {
public name: string; //public相当于公开的在外部是可以访问的;可以在当前类,子类,外部使用;
protected gender: string = '男'; //protected被保护的,当前类,和继承的子类可以使用;也可以设置默认值‘男’
private age: number = 27; //赋值默认值27;private是私有的,只能在当前的Person类使用;
constructor(name: string, /*gender: string,*/ public username: string) {
this.name = name;
this.username = username;
/*this.gender = gender;*/
}
printAge(age: number) {
this.age = age;
console.log(this.age);
this.setGender(this.gender);//setGender加上private ,可以在内部使用
}
/*private*/ setGender(gender: string) { //加上private 属性“setGender”为私有属性,只能在类“Person”中访问。
this.gender = gender;
console.log(gender);
}
}
const person = new Person('yaobinggt', /*'男',*/ 'yaouu');
console.log(person.name, /*person.gender,*/ person.username);//gender是protected(受保护的,无法在外部使用)
person.printAge(32);
person.setGender("女")
类的继承
父类 ↓↓↓
class Person {
public name: string;
protected gender: string = '男';
private age: number = 27;
constructor(name: string,public username: string) {//每个类都会自动触发的构造函数(constructor)
this.name = name;
this.username = username;
}
printAge(age: number) {
this.age = age;
console.log(this.age);
}
private setGender(gender: string) { //加上private 属性“setGender”为私有属性,只能在类“Person”中访问。
this.gender = gender;
}
printName(name: string) {
this.name = name;
console.log(this.name);
}
}
子类 ↓↓↓
student类继承于(extends) person类;子类继承(extends) 父类可以获得父类所有的内容,但是不能使用父类中私有(private) 的东西
class Student extends Person {
public studentId: number;
constructor(name: string, username: string, studentId: number) {
super(name, username);
//console.log(this.gender);//男
// console.log(this.age);//属性“age”为私有属性,只能在类“Person”中访问。
this.studentId = studentId;
// this.setGender('女'); //父类方法是是私有的
}
studentPrint() {
console.log(this.studentId);
}
printName(name: string) {//重写父类方法
this.name = name;
console.log(this.name);
}
}
const yaobinggt = new Student('姚冰', '姚UU', 20200810);
//console.log(yaobinggt.name, yaobinggt.username,);//姚冰 姚UU
console.log(yaobinggt);//Student {username: "姚UU", gender: "男", age: 27, name: "姚冰", studentId: 20200810}
yaobinggt.studentPrint();//20200810
yaobinggt.printAge(2);//可以调用父级方法
set get修饰词
用于隔离私有属性和可公开属性
const l = console.log;
class Person {
private _name: string = 'yaobinggt';//通常定义一个私有(private)属性,会加一个下划线;
//私有属性赋值(set)
set setName(val: string) {
this._name = val;
}
//私有属性取值(get)
get getName() {
return this._name;
}
}
//实例化一个person对象
let person = new Person();
l(person.getName);//yaobinggt
person.setName = 'yaouu';//赋值 yaouu
l(person.getName);//取值: yaouu
static 静态属性和方法
//class 静态属性和方法
const l = console.log;
class Person {
static PI: number = 3.14;//静态属性
static calcCircle(val: number): number {//静态方法
return this.PI * val;
}
}
l(Person.calcCircle(8));//25.12
namespace 命名空间
可以用来隔离我们环境变量的污染;在一个大的项目中我们可能起很多变量,有时候就会出现变量冲突,命名空间就能解决变量冲突的问题,同时命名空间可以一个大的TS文件,把一部分内容抽离到另外一个里面去;
要让外部调用就要加上export
const l = console.log;
namespace MyMath {
export const l = console.log;
export const PI: number = 3.14;
export function sumValue(num1: number, num2: number): number { //
return num1 + num2;
}
export function calcCircle(val: number) {
return PI * val;
}
}
const PI: number = 2.66;
MyMath.l(MyMath.sumValue(20, 10));//30
l(PI);//2.66
MyMath.l(PI);//2.66
MyMath.l(MyMath.PI);//3.14
命名空间拆分
首先以命名空间代码为例拆分为三个文件
calcCircle.ts
namespace MyMath {
const PI: number = 3.14;
export function calcCircle(val: number) {
return PI * val;
}
}
sumValue.ts
namespace MyMath {
export function sumValue(num1: number, num2: number): number {
return num1 + num2;
}
}
app.ts
const l = console.log;
l(MyMath.calcCircle(8));//25.12
l(MyMath.sumValue(5, 15));//20
然后到了最关键的一步,打开终端输入:
tsc --outfile app.js calcCircle.ts sumValue.ts app.ts
tsc:我们要执行的命令 --outfile:表示我们要输出的一个文件名字(所以这里输出的是app.js) 输出文件后面是要要把那些ts文件打包成app.js
多重命名空间
在calcCircle.ts代码内再添加一个命名空间,对外引用同样也要加上export
namespace MyMath {
//多重命名空间
export namespace Circle {
const PI: number = 3.14;
export function calcCircle(val: number) {
return PI * val;
}
}
}
app.ts如何引用:
const l = console.log;
l(MyMath.Circle.calcCircle(8));//25.12
命名空间引入
/// 在ts文件中表示要引用
/// <reference path="calcCircle.ts" />
/// <reference path="sumValue.ts" />
const l = console.log;
l(MyMath.Circle.calcCircle(8));//25.12
l(MyMath.sumValue(5, 15));//20
然后引入之后,只对app.ts进行编译就可以了
tsc app.ts --outFile app.js
模块module的使用
calcCircle.ts
export const PI: number = 3.14; //export 对外公开
export function calcCircle(val: number) {
return PI * val;
}
app.ts
const l = console.log;
//模块
import { PI, calcCircle } from './stuff/calcCircle'
l(PI);
有了app.ts,我首先要进行编译
- 命令行输入 tsc,然后编译成app.js:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var l = console.log;
var calcCircle_1 = require("./stuff/calcCircle");
l(calcCircle_1.PI);
//报错:exports is not defined
- 命令行输入 tsc --module commonjs app.ts,然后编译成app.js:
"use strict";
exports.__esModule = true;
var l = console.log;
var calcCircle_1 = require("./stuff/calcCircle");
l(calcCircle_1.PI);
//报错:exports is not defined
- 命令行输入 tsc --module amd app.ts,然后编译成app.js:
define(["require", "exports", "./stuff/calcCircle"], function (require, exports, calcCircle_1) {
"use strict";
exports.__esModule = true;
var l = console.log;
l(calcCircle_1.PI);
});
//报错: define is not defined
综上不管是commonjs、amd还是其他解析都无法将ts解析成浏览器识别的js;所以我们需要一个systemjs(2.0.0一下的版本)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TypeScript</title>
<script src="https://cdn.bootcdn.net/ajax/libs/systemjs/0.21.5/system.js"></script>
</head>
<body>
<script>
System.config({
baseUrl: "/",
packages: {
"/": {
"defaultExtension": "js"//让你的js可以被你的浏览器解读
}
}
})
System.import("app.js");
</script>
</body>
</html>
app.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var l = console.log;
//模块
var calcCircle_1 = require("./stuff/calcCircle");
l(calcCircle_1.PI);//3.14
l(calcCircle(32));//100.48
app.ts我们还可以换一种方法引入模块
sumValue.ts
export default function sumValue(num1: number, num2: number): number {
return num1 + num2;
}
const l = console.log;
//模块
// import { PI, calcCircle } from './stuff/calcCircle';
import * as Circl from './stuff/calcCircle';//另外一种引入方法
import sum from './stuff/sumValue';//另外一种引入方法
l(Circl.PI);//3.14
l(Circl.calcCircle(32));//100.48
l(sum(10, 6));//16
interface 接口
接口其实是在面向对象语言中是一个非常重要的概念,JS不是面向对象语言所以并没有接口这么一个概念,但是再TS中就有接口这么一个概念;可以通过接口把我们的所有属性,它的类型进行一个定义,它在某种意义上跟类型的别名很相识
//interfacr接口
interface Person {
name: string;
age: number;//单纯的冒号,必须要写的
sex?: string;//?: 可选的
readonly salary: number;//readonly只读不能修改
[propName: string]: any//任何名字可以赋任何值
greet(): void;//可以定义一个方法,没有返回值
}
type Person2 = {
name: string,
age: number
}
//interface可以继承,type不能继承
let person: Person = {
name: "yaobinggt",
age: 28,
sex: "box",
salary: 3000,
greet() {
console.log("I love litter UU")
}
}
//调用方法
person.greet();//I love litter UU
function printPerson(person: Person) {
console.log(`我叫${person.name},今年${person.age}了,性别${person.age},工资一个月${person.salary}`)
}
printPerson(person)
interface接口继承
//interfacr接口
interface PersonInterface {
name: string;
age: number;//单纯的冒号,必须要写的
sex?: string;//?: 可选的
readonly salary: number;//readonly只读不能修改
[propName: string]: any//任何名字可以赋任何值
greet(): void;//可以定义一个方法,没有返回值
}
//interface接口继承
interface Employee extends PersonInterface {
work: string;
}
const employee: Employee = {
name: 'yaobinggt',
age: 32,
salary: 6000,
sex: 'boy',
work: '前端',
greet() {
console.log('hello world')
}
}
console.log(employee);
employee.greet();
泛型(Generic)
在函数中使用泛型;让TS推断类型
function identify<T>(arg: T): T {
return arg;
}
const l = console.log;
l(identify<string>('string'));//可以明确指定类型
在接口中使用泛型:可以明确指定类型;也可以交给ts推断类型。
const l = console.log;
interface GenericIdentify {
<T>(age: T): T;
}
function identify<T>(arg: T): T {
return arg;
}
let myIdentify: GenericIdentify = identify;
//可以明确指定类型:
l(myIdentify<string>("yao-string"));//yao-string
//交给ts推断类型
l(myIdentify(30));//30
泛型还可以在接口中提升;不在函数里面定义;而是在接口上定义。
const l = console.log;
interface GenericIdentify<T> {
(age: T): T;
}
function identify<T>(arg: T): T {
return arg;
}
let myIdentify: GenericIdentify<number | string> = identify;//泛型在接口中提升以后要添加类型参数
//可以明确指定类型:
l(myIdentify("yao-string"));//yao-string
//交给ts推断类型
l(myIdentify(30));//30
为泛型添加约束
const l = console.log;
function getLength<T extends { length: any }>(obj: T): any {//给泛型制定了一个约束(extends),传递的参数一定要有length
return obj.length;
}
const obj = {
name: 'yaobinggt',
age: 28,
length: 12
}
l(getLength(obj));//12
const l = console.log;
function getLength<T extends number>(obj: T): any {//还可以让当前的泛型指定一个类型
return obj;
}
const obj = 28;//指定了类型,就要传对应的类型
l(getLength(obj));//28
泛型Generic类的应用
普通的类
const l = console.log;
class CountNumber {
number1: any;
number2: any;
constructor(num1: number, num2: number) {
this.number1 = num1;
this.number2 = num2;
}
calcalate(): number {
return this.number1 + this.number2;
}
}
const constNumber = new CountNumber(10, 12)
l(constNumber.calcalate());//22
添加泛型的类
const l = console.log;
class CountNumber<T> {
number1: T;
number2: T;
constructor(num1: T, num2: T) {
this.number1 = num1;
this.number2 = num2;
}
calcalate(): number {
return +this.number1 + +this.number2;
}
}
const constNumber = new CountNumber<string>("10", "12")
l(constNumber.calcalate());//120
还可以对泛型进行一个约束
const l = console.log;
class CountNumber<T extends number> {//对泛型约束为number
number1: T;
number2: T;
constructor(num1: T, num2: T) {
this.number1 = num1;
this.number2 = num2;
}
calcalate(): number {
return +this.number1 + +this.number2;
}
}
const constNumber = new CountNumber<number>(10, 12)//对应的也要是number
l(constNumber.calcalate());//22