TypeScript (是js的一个超集,完全兼容js,主要提供了类型系统和对ES6的支持)
浏览器只能识别js代码,ts-编译-js运行
Javascript(Esmascript标准的实现)组成:
Esmascript(浏览器脚本语言的标准。描述了该语言的语法和基本对象)、
DOM(描述了处理网页内容的方法和接口)、
BOM(描述了与浏览器进行交互的方法和接口)。
一.ts运行环境
1.创建.ts结尾的文件
let name:string = '100'
2.编译
npm i typescript -g 安装
tsc --init生成tsconfig.json配置文件(解决.ts和.js文件变量重名问题)
tsconfig.json配置文件属性说明:
-
target降级编译-兼容旧浏览器
-
strict严格模式-定义形参时也要定义类型(项目移植时可以关false)
eg:function say(content:string){} )
-
"rootDir":"./src"编译目录
-
"outDir":"./dist"输出目录
tsc xx.ts 手动编译某文件(将ts文件编译成js文件)
tsc -w 自动编译
在线环境:www.tslang.cn/play/index.… (可直接写ts代码)
二. ts基础语法
1. 基础数据类型:布尔值、数值、字符串、null、undefined、ES6新类型Symbol、ES10新类型BigInt
null,undefined是所有数据类型的子类型
let content: string = "hello";
content = "world";
let count: number = 20;
let un: undefined = undefined;
let nu: null = null;
let num:number = undefined//null/undefined,非严格模式下
2. 数组类型与对象类型(通过interface关键字定义)
// 数组
let arr: number[] = [1, 2, 3, 4];
let arr0:Array<number> = [1,2,3];
let arr1: Array<string> = ["a", "b", "c"];//'泛型'
// 对象
// 创建新的数据类型IPerson
interface IPerson{
name:string
age:number
}
// 创建类型为IPerson的obj对象,
let obj:IPerson = {
name:'rose',
age:21,
}
3. 联合类型(给一个变量指定多个类型)与任意类型any(项目迁移时用)
// 联合类型
let score: number|string = '90'
score = 100
// score = true//报错
// any 任意类型 js->ts
let msg: any = 'hello'
msg = 100
msg = true
4. 函数类型(形参类型,返回值类型 void-空值)
/**
* 函数类型
* 1. 形参类型
* 2. 返回值类型 void 空值(无返回值)
*/
function fn(): void {//无返回值
console.log("fn >>>>");
}
function fn1(): number {//有返回值
return 100;
}
/**
* @param name
* @param age 可选参数?
* @returns
*/
function fun(name: string, age?: number): string {
return "姓名是" + name + " 年龄是 " + age;
}
fun("jack",20);
5. 类型推论(在没有明确的指定类型的时候推测出一个类型)与类型断言as关键字(相当于类型转换。明确知道某个变量数据类型时,直接断言其类型)
// 类型推论 let mynumber: string
// 以第一个赋值类型为准
let mynumber = 'seven'
// mynumber = 7//推论为string,赋值number会报错
// 类型断言
// 当我们明确知道某个变量数据类型时,直接断言(指定)它的类型
let someValue:any = 'hello'
//let len:number = (<string>someValue).length//方法一
let len:number = (someValue as string).length//方法二
// 断言返回值类型
const divEle = document.getElementById('main_div') as HTMLElement
6. 泛型----在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。(先定义一个符号表示某个数据类型,使用时传具体类型)
/**
* 先定义一个符号T表示某个数据类型, T-> number, string, Array ...
* 在使用的时候传具体类型给T
* 泛型类 class
* 泛型方法 function
* 泛型接口 interface
*/
//泛型类 class
class Point<T>{
constructor(x:T,y:T){
console.log(x,y);
}
say(msg:T):string{
return 'hello'
}
}
const p1 = new Point<number>(102.32,45.34)
const p2 = new Point<string>('东经100度','北纬35.58度')
//泛型方法 function
function fun1<T>(msg:T):string{
console.log(msg)
return '这是泛型方法'
}
fun1<string>('泛型T')
fun1<number>(100)
//泛型接口 interface
interface IPerson1<T>{
name:string
age:number
score:T
}
//泛型约束
interface ILength{
length:number
}
/**
* 泛型约束extends,限制泛型一定有length属性
* @param arg
* @returns
*/
function loginLength<T extends ILength>(arg:T):number{
return arg.length
}
const len1:number = loginLength('hello')
const len2:number = loginLength([1,2,3])
// const len3:number = loginLength(100)
console.log(len1);
7. 类型别名(type关键字)
类型别名(type)与接口定义对象类型(interface)区别:
相同接口时属性会合并;类型别名属性不会合并
// 定义一个名为usernamestring类型别名,表示string字符串类型
type usernamestring = string
let username: usernamestring = 'jack'
// 定义一个名为ageType类型别名,表示string字符串和number类型
type ageType = number|string
let age1: ageType = '100'
let age2: ageType = '200'
// 定义名为IPerson2的类型别名,表示一个对象,对象中有name和age属性
type IPerson2 = {
name:string
age:number
}
// type IPerson2 = {
// score:number
// }
const obj1: IPerson2 = {
name:'jack',
age:20
}
// 类型别名与接口定义对象类型区别:相同接口时,属性会合并;类型别名属性不会合并
interface IPerson3{
name:string
age:number
}
interface IPerson3{
score:number
}
const obj2:IPerson3 = {
name:'rose',
age:21,
score:99
}
// 接口继承
// 动物
interface Animal{
name:string
}
// Dog
interface Dog extends Animal{
age:number
}
const huahua:Dog = {
name:'花花',
age:3
}
8. 元组类型(数组合并了不同类型的对象)与枚举类型enum关键字(对js标准数据类型的补充,可以为一组数值赋予友好的名字)
// 元祖类型
// 当我们向集合存储不同类型元素时考虑 元祖类型. 相同类型元素使用数组
let yz: [string,number,boolean] = ['hello',100,false]
// 枚举类型
//为一组数值赋予友好的名字
enum LightColor{
RED = '红灯',
YELLOW = '黄灯',
GREEN = '绿灯'
}
const currentLight = LightColor.RED
console.log('currentLight ',currentLight);
9. 类
TypeScript 可以使用三种访问修饰符: public、private和protected.
public修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是public 的
private修饰的属性或方法是私有的,不能在声明它的类的外部访问
protected 修饰的属性或方法是受保护的,它和private类似,区别是它在子类中也是允许被访问的
/**
* TypeScript 可以使用三种访问修饰符: public、prfvate和protected.
* public修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是public的
* private修饰的属性或方法是私有的,不能在声明它的类的外部访问
* protected修饰的属性或方法是受保护的,它和private类似,区别是它在子类中也是允许被访问的
*/
class Animal {
private name1;
public constructor(name1){
this.name1 = name1;
}
}
let a = new Animal('Jack');
console.log(a.name1);
a.name1 = 'Tom';
10. 模块化
es6模块化
暴露 export / export default say
导入import {say}/sayEat from 'a.js'
调用say()/sayEat()
export暴露,引入时名字不能改,并且要加{}
export default暴露,引入时名字可以改,不用加{}
ts特定模块语法(兼容es6)
moduleA.ts
function say(message:string):string{
return '说话内容 :' + message
}
export const message:string = 'hello world'
// 类型别名
export type Animal1 = {
name:string
}
// 接口
export interface IAmina2{
age:number
}
export default say
moduleB.ts
// import say from './moduleA'
// import { message } from './moduleA'
// import type {Animal1,IAmina2} from './moduleA'
import say, { message, type Animal1, type IAmina2 } from './moduleA'
import * as module from './moduleA'
// const msg:string = say(message)
// const obj3: Animal1 = { name: 'jack' }
// const obj4: IAmina2 = { age: 21 }
const msg: string = module.default(message)
console.log('msg ', msg);
const obj3: module.Animal1 = {
name: 'jack'
}
const obj4: module.IAmina2 = {
age: 21
}