❤️ 点赞关注,支持更多内容!
基础数据类型(8种)
let name: string = "ll";
let age: number = 18;
let isShow: boolean = true;
let hoh: undefined = undefined;
let nwn: null = null;
let obj: object = {name: 'll', age: 18};
let big: bigint = 100n;
let sym: symbol = Symbol("ll");
//可以赋予任意类型的值,可以在任意值上访问任何属性,调用任何方法,相当于Js
//any吸收一切类型,如果任一组成类型是any,则联合类型相当于any
let anyNever: any = 4
anyNever= "ll"
anyNever= false
anyNever.name
anyNever.getName()
any、unknown 区别
any | unknown |
---|---|
可以赋予任意类型的值 | 未知类型的值,需要进行类型检查或类型断言才能使用 |
可以在任意值上访问任何属性,调用任何方法 | 不可以在任意值上访问属性,调用方法,且unknown类型的值不能直接赋值给其他变量 |
never 类型 :是其他类型 (包括null 和 undefined )的子类型 ,代表从不会出现的值
意味着,声明never的变量只能被never类型所赋值
var a : undefined
a = undefined
var a : never
a = 123 //报错
a = (()=>{
throw new Error("错误")
})//自适应函数 (()=>{}),表示抛出一个异常,表示其他类型。
函数
JS中定义函数
function run (){
return 'run'
}
let run2 = function () {
return 'run2 '
}
TS定义函数类型需要定义输入参数类型和输出类型
输出类型可以忽略,默认返回void类型
1.输出类型 没有返回值 (如果一个函数没有返回值 使用:void,表示方法没有返回任何类型)
const fn1 = (param:string): void => {
console.log("给我传的值必须是字符哟");
console.log("我是没有返回值的箭头函数");
};
function fn2(param:string): void {
console.log("给我传的值必须是字符哟");
console.log("我是没有返回值的函数");
}
2.输出类型是number类型,其它类似
//匿名函数写法
let fun = function ():number{
return 123
}
//函数声明写法
function fun():number{
return 123
}
ts中定义方法传参
function getInfo(name:string,age:number):string{
return `${name}-${age}`
}
getInfo('zs',20)
默认参数
let fn5= (x: number, y: number=100): number => {
return x + y
}
fn5(100)
//y默认值是100,不会报错
let fn6= (x: number=100, y: number): number => {
return x + y
}
fn6(200) //报错 编译器会判定你只传了 x,没传 y。
//用户必须明确的传入 undefined值来获得默认值。
fn6(undefined,100)
可选参数
es5中里面的方法实参和形参可以不一样,但是ts中必须一样,如果不一样就需要配置可选参数
//参数后加个问号,代表是可选参数,
//可选参数必须要放在函数入参的最后面,不然会导致编译错误。
function fn4(x:number, y:number, z?:number):number {
console.log("给我传的值必须是数字x和y哟,你可以选择传数字z也可以不传哟");
return x + y
}
fn4(1,2)//如果不设置可选参数z?,z不传就会报错
剩余参数
function fn7(...args:number[]):number[]{
return args
}
函数重载
java中放的重载,指的是两个或两个以上同名函数,但它们的参数不一样。
ts中的重载,通过为同一个函数提供多个函数类型定义来试下多种功能的目的
function getInfo(name:string):string;
function getInfo(age:number):number;
function getInfot(str:any):any{
if(typeof str === 'string'){
return `我的年龄是${str}`
}else{
return `我的名字是${str}`
}
}
数组
使用泛型定义数组
let numbers: Array<number> = [1, 2, 3, 4, 5];
let strings: Array<string> = ['hello', 'world'];
定义空数组
let emptyArray: any[] = [];
使用构造函数定义数组
let numbers: number[] = new Array<number>(1, 2, 3, 4, 5);
let strings: string[] = new Array<string>('hello', 'world');
使用类型别名
使用场景:需要在多个地方使用相同类型的数组,你可以使用类型别名
type NumberArray = number[]
let numbers:NumberArray = [1,2,3,4]
使用接口定义数组结构
interface Person {
name: string;
age: number;
}
let people: Person[] = [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }];
元组
元组类型就是在定义数组的时候,类型和数据的个数一开始就已经限定好了。
let arr1 : [string,number,boolean] = [ '跳跳' , 520, true ]
类型断言
尖括号语法
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
as语法
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
联合类型
//语法格式 Type1|Type2|Type3
var val:string|number
val = 12
console.log("数字为 "+ val)
val = "Runoob"
console.log("字符串为 " + val)
接口 inferface
interface '名字' {
}
作用:
-
定义对象的结构
interface User { id: number; name: string; email: string; age?: number; // 可选参数 } const user: User = { id: 1, name: 'John Doe', email: 'john.doe@example.com', };
-
描述函数类型
interface SearchFunc { (source: string, subString: string): boolean; } const mySearch: SearchFunc = (source, subString) => { return source.includes(subString); };
SearchFunc 接口描述了一个接收两个字符串参数并返回布尔值的函数类型
-
实现类的接口
它允许类实现接口,确保类遵循特定的结构:
interface Printable { print(): void; } class Document implements Printable { print() { console.log('Printing document...'); } } const doc = new Document(); doc.print(); // 输出: Printing document...
-
扩展接口
可以继承其他接口,创建层次化的类型结构
interface Person { name: string; age: number; } interface Employee extends Person { employeeId: number; } const employee: Employee = { name: 'Jane Doe', age: 30, employeeId: 1234, };
Employee
接口继承了Person
接口,因此它包含了Person
的所有属性,并添加了employeeId
属性。 -
描述混合类型
在某些高级场景下,你可能需要描述一个既是函数又是对象的类型。
interface
可以帮助你做到这一点interface Counter { (start: number): string; interval: number; reset(): void; } const counter: Counter = (function (start: number) { let current = start; const c = function (start: number) { current = start; return `${current}`; } as Counter; c.interval = 1000; c.reset = function () { current = 0; }; return c; })(0); console.log(counter(10)); // 输出: 10 console.log(counter.interval); // 输出: 1000 counter.reset();
代码解释:
接口定义
interface Counter { (start: number): string; interval: number; reset(): void; }
这个接口定义了一个混合类型
Counter
,它有以下几个特性:- 是一个函数,接受一个
number
类型的参数start
,返回一个string
。 - 有一个
number
类型的属性interval
。 - 有一个
reset
方法,没有参数,返回值是void
。
实现接口的函数
const counter: Counter = (function (start: number) { let current = start; const c = function (start: number) { current = start; return `${current}`; } as Counter; c.interval = 1000; c.reset = function () { current = 0; }; return c; })(0);
- 是一个函数,接受一个
-
用于泛型接口
接口更具通用性
interface KeyValuePair<K, V> { key: K; value: V; } //在这个例子中,KeyValuePair接口使用了两个泛型参数K和V,可以用于表示任意类型的键值对。 const kvp: KeyValuePair<string, number> = { key: 'age', value: 30, };
枚举
通过enum来定义,作用:表示
enum Status {
success = 1,
error = 0
}
let s : Status = Status.success
if(s === 1) {
//表示成功
} else if(s === 0){
//表示失败
}
-
数字枚举
enum Color { Red = 2, Blue, Yellow } console.log(Color.Red, Color.Blue, Color.Yellow); // 2 3 4
// 指定部分字段,其他使用默认递增索引 enum Status { Ok = 200, Created, Accepted, BadRequest = 400, Unauthorized } console.log(Status.Created, Status.Accepted, Status.Unauthorized); // 201 202 401
//数字枚举在定义值时,可以使用计算值和常量。但是要注意,如果某个字段使用了计算值或常量,那么该字段后面紧接着的字段必须设置初始值,这里不能使用默认的递增值了 // 初值为计算值 const getValue = () => { return 0; }; enum ErrorIndex { a = getValue(), b, // error 枚举成员必须具有初始化的值 c } enum RightIndex { a = getValue(), b = 1, c } // 初值为常量 const Start = 1; enum Index { a = Start, b, // error 枚举成员必须具有初始化的值 c }
-
字符串枚举
定义值是字符串字面量的枚举称为字符串枚举,字符串枚举值要求每个字段的值都必须是字符串字面量,或者是该枚举值中另一个字符串枚举成员.
// 使用字符串字面量 enum Message { Error = "Sorry, error", Success = "Hoho, success" } console.log(Message.Error); // 'Sorry, error' // 使用枚举值中其他枚举成员 enum Message { Error = "error message", ServerError = Error, ClientError = Error } console.log(Message.Error); // 'error message' console.log(Message.ServerError); // 'error message'
-
反向映射,只支持数字枚举,不支持字符串枚举
enum Status { Success = 200, NotFound = 404, Error = 500 } console.log(Status["Success"]); // 200 console.log(Status[200]); // 'Success' console.log(Status[Status["Success"]]); // 'Success'
-
异构枚举
既有数字类型又有字符串类型
-
常量枚举
使用const
enum Status { Off, On } const enum Animal { Dog, Cat } const status = Status.On; const animal = Animal.Dog;
类
//最简单的类
function Person (){
this.name = "wl";/*属性*/
this.age = 20
this.fun = function(){
alert(this.name)/*方法---实例方法*/
}
}
//原型链上增加属性和方法
Person.prototype.sex = "男"
Person.prototype.work=function(){
console.log(this.name + '在学习')
}
//类里面的静态方法
Person.getInfo=function(){
console.log("我是静态方法,不用通过new Person来调用")
}
//调用静态方法
Person.getInfo()
//Web类继承Person类
function Web(){
Person.call(this)/*这叫对象冒充实现继承*/
}
let w = new Web()
w.fun()//弹框提示wl
w.work()//报错,w.work is not a function。--对象冒充可以继承构造函数里面的属性和方法,但是没法继承原型链上的属性和方法
Web.prototyp= new Person() // 原型链实现继承,可以继承构造函数里面的属性和方法也可以继承原型链上的属性和方法
/*原型链实现继承的问题*/
function Person(name,age){
this.name = name
this.age = age
this.run = function(){
alert(this.name + '在学习')
}
}
Person.prototype.work = function(){
alert(this.name + '在工作')
}
let p = new Person('wl',20)
p.run()//wl在学习
function Web(name,age){
}
Web.prototype = new Person()
let w = new Web('小小',200) //实例化子类的时候没法给父类传参
w.run()//undefined在学习
//原型链+构造函数 组合继承模式 弥补缺陷
function Person(name,age){
this.name = name
this.age = age
this.run = function(){
alert(this.name + '在学习')
}
}
Person.prototype.work = function(){
alert(this.name + '在工作')
}
function Web(name,age){
Person.call(this,name,age)//对象冒充,实例化子类传参给父类
}
Web.prototype = new Person()
//Web.prototype = Person.prototype 也可以实现原型链继承
let w = new Web('小小',200)
w.run()//小小在学习
w.work()//小小在工作
TS中定义类
function Person(name){
this.name=name
this.run=function(){
console.log(this.name)
}
}
let p = new Person("张三")
p.run()//这是es5
//----------------
class Person{
name:string;//属性 ,省略了public关键字
//构造函数实例化类的时候触发
constructor(n:string){
this.name=n
}
run():void{
alert(this.name)
}
}
let p =new Person('wl')
p.run()
TS中如何实现继承
/*extends和super*/
/*步骤1 定义一个类 */
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
run(): string {
return `${this.name} is running`;
}
}
var p = new Person("大王");
alert(p.run());
/* 步骤二 */
class Web extends Person {
constructor(name: string) {
super(name);
}
/* 子类不仅可以继承父类的属性和方法
还可以扩展子集的属性和方法 */
work(): void {
alert(this.name + " is working");
}
/* 如何父类和子类都有相同的方法,调用的时候会首先调用子类的 */
run(): string {
return `${this.name} is running2`;
}
}
var w = new Web("小李");
//
alert(w.run());
类里面的 修饰符 ts提供了3种
修饰符 | 作用 |
---|---|
public | 类 子类 外部 可访问 |
protected | 类 子类可访问 |
private | 类可访问 |
静态属性 静态方法
function Person() {
this.run1 = function () {};/* 实例化方法 */
}
Person.run2 = function () {}; /* 静态方法 */
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
run() {
return `${this.name} is running`;/* 实例方法 */
}
static print() { /* 静态方法 --静态方法里面没法直接调用类里面的属性 */
alert("print方法");
}
}
Person.print()
// 调用静态方法,不需要实例化,直接Person.print()
多态
定义:父类定义一个方法不去实现,让继承它的子类去实现,每一个子类有不同的表现
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
//父类定义了一个方法
eat() {}
}
class Dog extends Animal {
constructor(name: string) {
super(name);
}
// 继承它的子类去实现
eat() {
return this.name + "吃骨头";
}
}
class Cat extends Animal {
constructor(name: string) {
super(name);
}
// 每个子类的表现不一样
eat() {
return this.name + "吃鱼";
}
}
抽象类
定义:他是提供其他继承的基类,不能直接被实例化
用abstract关键字定义抽象类和抽象方法,抽象类种的抽象方法不包含具体实现并且必须在派生类种实现
abstract抽象方法只能放在抽象类里面
抽象类和抽象方法用来定义标准 Animal 这个类要求它的子类必须包含eat方法
abstract class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
abstract eat(): any; /* 抽象方法只能出现在抽象类里面 */
}
// var a = new Animal(); /* 错误写法,无法直接实例化 */
class Dog extends Animal {
constructor(name: string) {
super(name);
}
/* 抽象类的子类必须实现抽象类里面的抽象方法 */
eat() {
alert(this.name + "吃骨头");
}
}
let d = new Dog("小狗");
d.eat();