概述
typeScript是js的超集,会被编译成javaScrip代码。
安装TypeScript
npm install -g typescript
查看安装成功
tsc -V
vscode手动编译代码
tsc 加文件路径 编译出相同名称的一个js文件
tsc helloworld.ts
自动编译
- 生成tsconfig.json文件
tsc --init
- 修改tsconfig.json配置
"outDir": "./js",//编译的js文件位置
"strict": false, //是否开启严格模式
- 启动监视任务
Terminal -> run Task ->Show All Tasks -> tsc:watch…
创建ts文件就会编译生成一个js文件。
类型注解:
类型注解是一种轻量级的为函数或变量添加约束的方式。
类型不对会报错;而因为js是弱类型语言,故还是可以编译成js。
编译看到错误:
Argument of type 'number[]' is not assignable to parameter of type 'string'.
接口
interface 规定了结构,如果结构不一样则会报错
interface Iperson {
firstName: String;
lastName: String;
}
function showFullName(person:Iperson) {
return person.firstName +'_'+ person.lastName;
}
const person ={
firstName:'hh',
lastName:'wy'
}
console.log(showFullName(person))
加入我注释person 的firstName,则报错:
类
interface Iperson {
firstName: String;
lastName: String;
}
class Person {
// 定义公共的字段(属性)
firstName: String;
lastName: String;
fullName: String;
constructor(firstName: String, lastName: String) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = this.firstName + "-" + this.lastName;
}
}
const person = new Person("诸葛", "孔明");
function showFullName(person: Iperson) {
return person.firstName + "_" + person.lastName;
}
console.log(showFullName(person));
typeScript的常用使用
ts中变量一开始是什么变量,后期赋值时也只能用这个类型的数据,不允许用其他类型的数据赋值给当前这个变量。
1. 基础类型
- 布尔值 boolean
let isDone: boolean = false;
isDone = true;
- 数字类型 number
let a1: number = 10 // 十进制
let a2: number = 0b1010 // 二进制
let a3: number = 0o12 // 八进制
let a4: number = 0xa // 十六进制
- 字符串 string
let name: string=''
- null和undefined
null和undefined都可以作为其他类型的子类型。可以赋值给其他类型的变量。
let u: undefined = undefined
let n: null = null
let name :string = null//关闭严格模式下不会报错
- 数组
数组定义后,里面的数据类型和定义的数据类型要保持一致,否则会报错。
数组定义方式1:
let arr1 :number[] =[1,2,2]//数组里面只能是number的类型
数组定义方式2:(泛型的存储方式)
语法: let 变量名: Array<数据类型> = [数组]
let arr1 :Array<number> =[1,2,2]
- 元组
定义数组的时候,类型和数据的个数一开始就已经限定了,可以不是同一类型。
元组类型时候的时候,数据的类型的位置和数据的个数应该在和定义元组的时候的数据类型及位置应该是一致的。
let t1: [string, number]
t1 = ['hello', 10] // OK
t1 = [10, 'hello'] // Error
- 枚举 enum
编号从0开始
enum Color {
Red,
Green,
Blue
}
let myColor: Color = Color.Green
console.log(myColor, Color.Red, Color.Blue)
可以手动赋值
enum Color {
Red=2,
Green=3,
Blue=122
}
- any
编程阶段不知道数据类型的,可以定义任何类型。
当一个数组中要存储多个数据,个数不确定,类型不确定,也可以用any。这种情况下编译时没有错误操作的提示信息。
let str :any ='9000'
let str :any =45
let str :any =[1,'字符串']
- void
表示没有任何类型
当一个函数没有返回值时,你通常会见到其返回值类型是 void,一般用来说明函数的返回值不能是undefined和null之外的值。
function fn(): void {
console.log('fn()')
// return undefined
// return null
// return 1 // error
}
只能为它赋予 undefined 和 null,意义并不大。
let unusable: void = undefined
- object
function getObj (obj:object) : object{
return {
name:'123
}
}
- 联合类型
表示取值可以时多种类型中的一种
//参数可以是数字类型或字符串类型
function getString(str:string|number) :string{}
- 类型断言
告诉编译器我知道我在干嘛,没有运行时的影响,只是在编译的时候影响。
语法方式:
<类型>变量名
值 as 类型
function getString(str:string|number) :string{
if((<string>str).length){
return (<string>str).length
// 或者 return (str as string).length
}else{
return str.toString().length
}
}
- 类型推断
TS会在没有明确的指定类型的时候推测出一个类型。
/* 定义变量时赋值了, 推断为对应的类型 */
let b9 = 123 // number
// b9 = 'abc' // error
/* 定义变量时没有赋值, 推断为any类型 */
let b10 // any类型
b10 = 123
b10 = 'abc'
2. 接口 interface
使用接口来定义对象的类型。
接口时对象的状态(属性)和行为(方法)的抽象(描述)。
限定或约束对象中的属性数据。
只读属性:readonly
readonly id:number//只读属性
?可有可无
sex?:string
示例:
interface IPerson{
readonly id:number//只读属性
name:string
age:number
sex?:string//加上❓表示可以有 可以没有
}
//person少一个则报错
const person:IPerson={
id:1,
name:'hy',
age:18,
sex:'女’
}
- 函数类型
通过接口的方式作为函数的类型来使用,参数列表里的每个参数都需要名字和类型。
interface SearchFunc(){
(source:string,subString:string):boolean
}
const mySearch: SearchFunc = function (source: string, sub: string): boolean {
return source.search(sub) > -1
}
console.log(mySearch('abcd', 'bc'))
- 类类型 implements
类的类型。类可以实现一个接口也可以实现多个接口,注意接口中的内容要真正的实现。
//定义一个接口
interface IFly{
//该方法中什么都没有
fly()
}
interface ISwim{
//该方法中什么都没有
swim()
}
//定义一个类。这个类的类型就是上面的接口,实际上也可以认为IFly约束了当前的这个person类
class Person implements IFly{
fly(){
console.log('1234')
}
}
//一个类也可以同时被多个接口约束
class Person2 implements ISwim,IFly{
fly(){
console.log('1234')
}
swim(){
console.log('1234')
}
}
const person=new Person()
const person2=new Person2()
person.fly()
person2.fly()
person2.swim()
- 继承 extends
接口和接口之间叫继承,类和接口之间叫实现。
//接口可以继承其他的多个接口
interface IMflayAndSwim extends Ifly,ISwim{}
3 . 类
可以理解为模板,通过模板实例化对象。面向对象的编程思想。
class Person{
name:string,
age:number,
gender:string,
//默认值 age=18
constructor(name:string='',age:number=18,gender:string){
this.name=name
this.age=age
this.gender=gender
},
SayHi(str:string){
console.log(`大家好,我是${this.name}`+str)
}
}
const person=new Person()
person.SayHi()
-
继承
类与类之间的关系。 -
A类继承了B类 此时A类叫子类(派生类),B类叫基类(超类/父类)。 类和类之间如果有继承关系,需要使用extends关键字
-
子类中可以调用父类中的构造函数,使用的是super关键字(包括调用父类中的实例方法,可以可以使用super)
-
子类中可以重写父类的方法
class Students extends Person{
constructor(name:string='',age:number=18,gender:string){
//调用父类中的构造函数,使用suoer
super(name,age,gender)
},
SayHi(){
console.log('学生类中的方法')
super.SayHi('haha')
}
}
- 类的修饰符
类中的成员的修饰符,主要是描述类中的成员(属性、构造函数、方法)的可访问性。
public:默认修饰符,公共的,任何位置都可以访问类中的成员。
private:私有的,外部无法访问这个成员数据,子类中也是无法访问该数据的。
protected:只能在内部以及字类中访问,外部不能访问。
class Person{
readonly name:string,
//public name:string,
constructor(name:string){
this.name=name
}
eat(){
console.log('加油啊',this.name)
}
}
readonly修饰符:只读不能修改。构造函数中可以对只读的属性成员的数据进行修改。如果构造函数中没有任何参数,类中的属性成员此时已经使用readonly进行修饰,那么外部也是不能对这个属性值修改的。
构造函数中的参数,一旦使用readonly 修饰后,就会有对应的一个属性成员。外部也是无法修改类中的属性成员的值的。(同样的public等修饰符修饰后都会自动给类增加对应的属性成员,属性与修饰符定义的一样)
例如:构造函数中的参数,一旦使用readonly 修饰后,Person就会有name属性成员。
class Person{
constructor( readonly name:string){//name参数属性,这里不写readonly会报错
this.name=name
}
}
- 存取器
TypeScript 支持通过 getters/setters 来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。
只有两个都有的话,就可以又读取又设置。
class Person {
firstName: string = 'A'
lastName: string = 'B'
constructor(firstName:string, lastName: string){
this.firstName=firstName
this.lastName=lastName
}
//读取器--负责读取数据的
get fullName () {
return this.firstName + '-' + this.lastName
}
//设置器--负责设置数据的
set fullName (value) {
const names = value.split('-')
this.firstName = names[0]
this.lastName = names[1]
}
}
const p = new Person()
console.log(p.fullName)
p.fullName='冲_a'//如果没set则会报错,不能修改
- 静态属性
static 修饰的属性或方法,在使用的时候是通过 类名.静态属性 的方式调用,不需要实例化。
/*
静态属性, 是类对象的属性
非静态属性, 是类的实例对象的属性
*/
class Person {
name1: string = 'A'
static name2: string = 'B'
constructor(name:string){
//this.name2=name 会报错,因为name2是静态属性,不能通过实例对象来调用
}
}
console.log(Person.name2)
console.log(new Person().name1)
- 抽象类
抽象类做为其它派生类的基类使用。 它们不能被实例化。不同于接口,抽象类可以包含成员的实现细节。 abstract 关键字是用于定义抽象类和在抽象类内部定义抽象方法。为了让 子类 实例化以及实现内部的抽象方法。
抽象类的目的或作用最终都是为子类服务的。
abstract class Animal{
abstract eat()//抽象方法不能有具体的实现
//理解:每个动物吃的 方式都不一样,所以不能用统一的进行描述
}
class dog extends Animal{
//重新的实现抽象类中的方法,此时这个方法就是dog的实例方法
eat(){
console.log('舔着吃')
}
}
const ani:Animal =new Animal()//报错,,不能实例化抽象类的对象
- 多态
父类型的引用指向了子类型的对象,不同类型的对象正对相同的方法,产生了不同的行为。
如果子类型有扩展的方法, 不能让子类型引用指向父类型的实例 。
如果子类型没有扩展的方法, 可以让子类型引用指向父类型的实例。
class Animal{
name:string
// 构造函数
constructor(name:string) {
this.name=name
}
run(distance:number){
console.log(`跑了${distance}米这么远的距离`
}
}
class Dog extends Animal{
constructor(name:string) {
super(name)
}
//实例方法,重写父类中的实例方法
run(distance:number=6){
console.log(`跑了${distance}米这么远的距离`
}
}
class Pig extends Animal{
constructor(name:string) {
super(name)
}
//实例方法,重写父类中的实例方法
run(distance:number=10){
console.log(`跑了${distance}米这么远的距离`
}
}
const ani:Animal =new Animal('动物')
//父子类型创建字类的对象
const dog1:Anmial = new Dog('雪雪')
4.函数
js中
// 命名函数
function add(x, y) {
return x + y
}
// 匿名函数
let myAdd = function(x, y) {
return x + y;
}
ts
function add(x: number, y: number): number {//参数都是Number类型,返回值也是number
return x + y
}
let myAdd = function(x: number, y: number): number {
return x + y
}
完整写法
///(x: number, y: number) => number当前函数的类型
let myAdd2: (x: number, y: number) => number =
function(x: number, y: number): number {
return x + y
}
默认参数:在函数申明的时候,内部的参数有自己的默认值
可选参数:函数在申明的时候,内部参数使用了?修饰,表示该参数可传可不传。
function(name:string,fullname ?:string)
剩余参数(rest参数):放在函数申明的时候的最后一个参数。
//...args:string[]:剩余参数放在了一个字符串数组中
function showMsag(name:string,...args:string[]){}
- 函数重载
函数名字相同,函数的参数及个数不同。
在JS中, 由于弱类型的特点和形参与实参可以不匹配, 是没有函数重载这一说的 但在TS中, 与其它面向对象的语言(如Java)就存在此语法。
function add (x: string, y: string): string
function add (x: number, y: number): number
// 定义函数实现
function add(x: string | number, y: string | number): string | number {
// 在实现上我们要注意严格判断两个参数的类型是否相等,而不能简单的写一个 x + y
if (typeof x === 'string' && typeof y === 'string') {
return x + y
} else if (typeof x === 'number' && typeof y === 'number') {
return x + y
}
}
console.log(add(1, 2))
console.log(add('a', 'b'))
5.泛型
在定义接口、函数、类的时候不能预先确定数据的类型,而是使用函数、接口、类的时候才能确定数据的类型。
//定义:
function getArr<T>(num:T,count:number):number[]{
const arr :Array<T>=[]
for((let i=0;i<count,i++){
arr.push(value)
}
return arr
}
//使用:
const arr=getArr<number>(100.23,3)
- 多个泛型参数的函数
function swap <K, V> (a: K, b: V): [K, V] {
return [a, b]
}
const result = swap<string, number>('abc', 123)
console.log(result[0].length, result[1].toFixed())
- 泛型接口
在定义类时, 为类中的属性或方法定义泛型类型 在创建类的实例时, 再指定特定的泛型类型
interface IBaseCRUD<T>{
data:Array<T>
add:(t:T)=>T
getUserId:(id:number)=> T
constructor(name:string,age:number){
this.name=name
this.age=age
}
}
class userCRUD implements IBaseCRUD<user>{
data:Array<user> =[]
add:(t:user):user{
user.id=Date.now()+Math.random()
this.data.push(user)
return user
}
getUserId:(id:number): user{
return this.data.find(user=>user.id===id)
}
}
//实例化添加用户信息对象的类
class User{
id?:number
name:string
age:number
}
const userCrud:userCRUD =new userCRUD()
userCRUD.add(new userCRUD('jack',20))
- 泛型类
class GenericNumber<T> {
zeroValue: T
add: (x: T, y: T) => T
}
let myGenericNumber = new GenericNumber<number>()
myGenericNumber.zeroValue = 0
myGenericNumber.add = function(x, y) {
return x + y
}
let myGenericString = new GenericNumber<string>()
myGenericString.zeroValue = 'abc'
myGenericString.add = function(x, y) {
return x + y
}
console.log(myGenericString.add(myGenericString.zeroValue, 'test'))
console.log(myGenericNumber.add(myGenericNumber.zeroValue, 12))
- 泛型约束
interface Lengthwise {
length: number;
}
// 指定泛型约束
function fn2 <T extends Lengthwise>(x: T): void {
console.log(x.length)
}
console.log(fn2<string>('what' ))
console.log(fn2<number>(2 ))//必须有length属性
6. 其他
- 申明文件
当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能
需要定义
一般声明文件都会单独写成一个 xxx.d.ts 文件
declare var jQuery: (selector: string) => any;
jQuery('#foo');
当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。
声明语句: 如果需要ts对新的语法进行检查, 需要要加载了对应的类型说明代码
declare var jQuery: (selector: string) => any;
声明文件: 把声明语句放到一个单独的文件(jQuery.d.ts)中, ts会自动解析到项目中所有声明文件
下载声明文件:
npm install @types/jquery --save-dev
- 内置对象
ECMAScript 的内置对象:
Boolean
Number
String
Date
RegExp
Error
/* 1. ECMAScript 的内置对象 */
let b: Boolean = new Boolean(1)
let n: Number = new Number(true)
let s: String = new String('abc')
let d: Date = new Date()
let r: RegExp = /^1/
let e: Error = new Error('error message')
b = true
BOM 和 DOM 的内置对象:
Window
Document
HTMLElement
DocumentFragment
Event
NodeList
const div: HTMLElement = document.getElementById('test')
const divs: NodeList = document.querySelectorAll('div')
document.addEventListener('click', (event: MouseEvent) => {
console.dir(event.target)
})
const fragment: DocumentFragment = document.createDocumentFragment()
最后
以上就是丰富老鼠为你收集整理的初识typeScript的全部内容,希望文章能够帮你解决初识typeScript所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复