一、类型定义
1.1 基本类型定义
let count : number = 1;
1.2 对象类型定义
// 方法一
type objType = { name: string, age: number }
const obj = <objType>{
name: "chang",
age: 18
}
// 方法二
const obj : {
name : string ,
age : number
} = {
name : 'chang',
age : 20
}
console.log(obj);
1.3 数组类型定义
// 定义一个字符串数组
const str_arr: string[] = ['str1', 'str2']
console.log(str_arr);
// 定义一个string,number都具有的数组
const str_num_arr: (string | number)[] = ['str1', 11, 'str2', 20]
console.log(str_num_arr);
// 对象类型的数组
type objType = { name: string, age: number }
const obj_arr:objType[] = [
{ name: 'zs', age: 20 },
{ name: 'ls', age: 22 },
]
for (let item of obj_arr) {
console.log(item);
}
1.4 元组类型的定义
// 元组数据类型定义
const person: [number, string] = [20, 'chang']
console.log(person);
1.5 类类型定义
class Person {
name: string
}
const p1: Person = new Person()
p1.name = 'chang'
console.log(p1);
1.6 函数类型 定义
// 创建一个参数为 字符串类型,返回值为字符串类型的函数
type fnType = (param: string) => string
const func: fnType = (param) => {
console.log(param);
return 'success'
}
const fun1 = func('hello')
console.log(fun1);
1.6.1 有关函数返回值
// 函数参数为简单数据类型时
// 创建一个加法函数,返回两个数字类型数据的和
function add(num1: number, num2: number): number {
return num1 + num2
}
console.log(add(1, 2));
// 函数参数为对象时
function add({ one, two }: { one: number, two: number }) {
return one + two
}
const total = add({ one: 1, two: 2 })
console.log(total); //3
1.7 联合类型和类型断言
interface Waiter {
anjiao: boolean;
say: () => {}
}
interface Teacher {
anjiao: boolean;
skill: () => {}
}
function judge(person: Waiter | Teacher) {
// person:Waiter | Teacher 这就是联合类型
// // 方法一
// if (person.anjiao) {
// (person as Teacher).skill() // as 类型断言, 如果一个人会按脚那么就作为技师,调用技师的方法。
// } else {
// (person as Waiter).say()
// }
// 方法二
if ('skill' in person) { // 使用in 判断一个方法是否在一个实例上
person.skill()
} else {
person.say()
}
// 方法三
// 使用typeof 进行类型的判断
}
// 类型保护 方法四 instanceOf
class NumObj {
'count': number
}
function addObj(first: object | NumObj, second: object | NumObj) {
if (first instanceof NumObj && second instanceof NumObj) {
// 当两个参数都属于指定对象类型的时候
return first.count + second.count
}
return 0
}
1.8 枚举类型
enum Status { // 定义一个枚举类型
ANMO,
SPA,
DBJ
} // 默认情况下枚举类型的索引是从0开始的
function getServe(status: any) {
if (status === Status.ANMO) {
return 'anmo'
} else if (status === Status.SPA) {
return 'spa'
} else if (status === Status.DBJ) {
return 'dbj'
}
}
console.log(Status); // { '0': 'ANMO', '1': 'SPA', '2': 'DBJ', ANMO: 0, SPA: 1, DBJ: 2 }
const res = getServe(0)
console.log(res); // anmo
1.8.1 默认索引
一般情况下,枚举类型的索引默认是从0开始的,如果想改变这种索引可以:
enum Status { // 定义一个枚举类型
ANMO = 1,
SPA,
DBJ
}
console.log(Status); // { '1': 'ANMO', '2': 'SPA', '3': 'DBJ', ANMO: 1, SPA: 2, DBJ: 3 }
二、接口
2.1 基本接口定义与使用
interface Person {
name: string; // 字符串类型的name属性
age?: number; // 可选属性age
readonly sex: string; // 只读属性 sex
[propname: string]: any;
// 任意多个字符串类型的属性,值为any
say():void; // 一个空类型的函数
}
const arr: Person[] = [
{ name: 'chang', age: 20, sex: 'boy', height: 170 },
{ name: 'zs', age: 20, sex: 'gril', height: 180 }
]
// 接口应用
const p1: Person = {
name: '小红',
age: 18,
sex: 'boy',
height: 180,
say() {
console.log('hello');
}
}
p1.say()
附加: readonly 和const 的区别
readonly:作为属性使用。 const :作为变量使用。
// const
const obj = {
name: 'zs'
}
obj.name = 'lx' // 对于obj的属性可以进行更改
obj = {} // 这里会报错, 对于obj本身变量 不能进行修改
2.2 接口的继承
interface Person {
name: string; // 字符串类型的name属性
age?: number; // 可选属性age
readonly sex: string; // 只读属性 sex
[propname: string]: any;
// 任意多个字符串类型的属性,值为any
say(): void;
}
interface girl extends Person {
hairColod: string
}
三、class类
3.1 类的基本使用(定义继承)
class Animal {
name: string
constructor(theName: string) { // 构造函数 得到一个字符串格式的名字参数
this.name = theName
}
move(distance: number): string {
return `${this.name} move ${distance} meter.`
}
}
class Horse extends Animal {
// 子类对于父类的继承
constructor(theName: string) {
super(theName)
}
// 子类对于父类的重写
move(distance: number): string {
console.log('Horse');
return super.move(distance)
}
}
const h1 = new Horse('的卢')
const res = h1.move(56)
console.log(res); // Horse\n的卢 move 46 meter.
3.2 类的属性修饰符
public private protected readonly
public
:默认情况下为public。
private
:不能在声明它的类的外部访问。
protected
:可以在声明它的类和它的子类中访问。
readonly
: 只读属性
class Animal {
protected name: string; // 当为private的时候,子类不能访问到父类的私有属性
constructor(theName: string) { this.name = theName; }
getName() {
return `${this.name}`
}
}
class Rhino extends Animal {
constructor() {
super("Rhino");
console.log(this.name); // 当为protected的时候可以访问到
}
}
let animal = new Rhino();
3.2 类的Getter、Setter和static
class Animal {
private name: string;
constructor(theName: string) { this.name = theName; }
get Pname() {
return this.name
}
set Pname(name:string){
this.name = name
}
}
const a1 = new Animal('monkey')
console.log(a1.Pname); // monkey
a1.Pname = 'donkey'
console.log(a1.Pname); // donkey
3.3 静态属性static
无需实例化就可以调用类里面的静态方法
class Girl{
static sayLove(){
console.log('I love you');
}
}
Girl.sayLove() // I love you
3.4 抽象类 abstract
// 抽象类的定义,被继承者必须带有该抽象类的抽象方法
abstract class Girl {
abstract skill()
}
class Waiter extends Girl{
skill(){
console.log('服务员,端茶倒水');
}
}
class BaseTeacher extends Girl{
skill(){
console.log('基础技师,泰式按摩');
}
}
class SeniorTeacher extends Girl{
skill(){
console.log('高级技师,SPA全身按摩');
}
}
4. tsconfig.json
1. ts的配置文件
安装完typescript之后,在文件夹中使用tsc -init
出现tsconfig.json
配置文件。
2. 基本的配置说明
"include":[], /* 需要编译的文件数组 */
"exclude":[], /* 不编译的文件数组 */
"file":[], /* 与include作用一样 */
"outFile":'./', /* 将多个文件编译成单个文件,不在支持common.js-> AMD */
"removeComments": true, /* 去掉注释 */
"strict": true, /* 是否使用严格模式 */
"noImplicitAny": true, /* 允许any类型的数据格式不用特意声明 */
"strictNullChecks": true, /* 不允许Null值出现 */
"outDir": "./", /* 出口文件夹 */
"rootDir": "./", /* 入口文件夹 */
"sourceMap": true, /* ts文件和js文件的映射 */
"noUnusedLocals": true, /* 无用的变量编译前会提示 */
"noUnusedParameters": true, /* 无用的方法编译前会提示 */
5 泛型
个人理解: 动态格式的规定
5.1 基本的泛型使用
function join<T>(first: T, second: T) {
return `${first}-${second}`
}
// 基本的泛型,规定函数的两个参数的类型必须一致
const res = join<string>('hello', 'world')
console.log(res);
5.2 泛型中使用数组
// 泛型中数组的使用
function getArr<T>(param: T[]) {
// function getArr<T>(param: Array<T>){
return param
}
const res = getArr<string>(['123', '456'])
5.2 多个泛型的定义
function join<T, P>(first: T, second: P) {
return `${first}-${second}`
}
// 基本的泛型,规定函数的两个参数的类型必须一致
const res = join<string, number>('hello', 1)
// 泛型的类型推断
// const res = join('hello', 1) //直接写也是可以的,但是不推荐
console.log(res);
5.3 泛型在类中的基本使用
class XJJ<T>{
constructor(private girls:T[]){}
getGirl(index:number):T{
return this.girls[index]
}
}
const setGirls = new XJJ<string>(['王冰冰','范冰冰','高圆圆'])
console.log(setGirls.getGirl(1));
5.4 泛型约束
interface Girl{
name : string
}
class XJJ<T extends Girl>{
constructor(private girls:T[]){}
getGirl(index:number):string{
// 返回值为name,name的类型为string,返回值为string
return this.girls[index].name
}
}
const setGirls = new XJJ([
{name:'王冰冰'},
{name:'范冰冰'},
{name:'高圆圆'}
])
console.log(setGirls.getGirl(1)); // 范冰冰
6. 命名空间的使用
6.1 基本使用
命名空间这个语法,很类似编程中常说的模块化思想,每个模块有自己的环境,不会污染其他模块,不会有全局变量产生。
命名空间声明的关键词是namespace
比如声明一个namespace Home
,需要暴露出去的类,可以使用export
关键词,这样只有暴漏出去的类是全局的,其他的不会再生成全局污染了。
namespace Home {
class Header {
constructor() {
const elem = document.createElement("div");
elem.innerText = "This is Header";
document.body.appendChild(elem);
}
}
class Content {
constructor() {
const elem = document.createElement("div");
elem.innerText = "This is Content";
document.body.appendChild(elem);
}
}
class Footer {
constructor() {
const elem = document.createElement("div");
elem.innerText = "This is Footer";
document.body.appendChild(elem);
}
}
export class Page {
constructor() {
new Header();
new Content();
new Footer();
}
}
}
<!DOCTYPE html>
<html lang="en">
<body>
<script>
new Home.Page()
</script>
</body>
</html>
6.2 子命名空间
namespace Components {
export namespace SubComponents {
export class Test {}
}
}
// 使用
Components.SubComponents.Test