类型

类型 例子 描述
number 1,2,-2 任意数字
string 'hi',"hi" 任意字符串
boolean true,false 布尔值或者true false
字面量 其本身 限制变量的值就是该字面量的值
any * 任意类型
unknown * 类型安全的any
void 空值(undefined) 没有值或者undefined
never 没有值 不能是任意值
array [1,1,2] 任意js数组
object {name:"孙悟空"} 任意js对象
tuple [4,5] 元素,TS新类型,固定长度的数组
enum enum{A,B} 枚举,TS新类型

接口interface与类型别名type

区别:

接口,只能为对象指定类型

类型别名,不仅可以给对象指定类型,实际上可以为任意类型指定别名

//接口
interface IPerson = {
name: string
age: number
sayHi(): void
} // 类型别名
type IPerson = {
name: string
age: number
sayHi(): void
} let person: IPerson = {
name: '刘老师',
age: 18,
sayHi() {}
} //类型别名
type NumStr = number | string let numStr: NumStr = 33
let numStr2: NumStr = '66'

字面量类型

思考以下代码,两个变量的类型分别是什么?

let str1 ='Hello Ts'
const str2 : 'Hello Ts'

通过 TS 类型推论机制,可以得到答案:

\1. 变量 str1 的类型为:string。

\2. 变量 str2 的类型为:'Hello TS'。

解释:

\1. str1 是一个变量(let),它的值可以是任意字符串,所以类型为:string。

\2. str2 是一个常量(const),它的值不能变化只能是 'Hello TS',所以,它的类型为:'Hello TS'。

注意:此处的 'Hello TS',就是一个字面量类型。也就是说某个特定的字符串也可以作为 TS 中的类型。

除字符串外,任意的 JS 字面量(比如,对象、数字等)都可以作为类型使用。

let str1 = 'Hello TS'

const str2: 'Hello TS' = 'Hello TS'

let age: 18 = 18

使用模式:字面量类型配合联合类型一起使用。

使用场景:用来表示一组明确的可选值列表。

比如,在贪吃蛇游戏中,游戏的方向的可选值只能是上、下、左、右中的任意一个。

解释:参数 direction 的值只能是 up/down/left/right 中的任意一个。

优势:相比于 string 类型,使用字面量类型更加精确、严谨


function changeDirection(direction: 'up' | 'down' | 'left' | 'right') {} changeDirection('left')

枚举类型

//枚举
/**
*enum
*/
enum Gender {
Male = 0,//可以写=0 也可以不写
Female = 1,
} let i1: { name: string; gender: Gender };
i1 = {
name: "孙悟空",
gender: Gender.Male,
};
console.log(i1.gender === Gender.Female);
// 枚举:

enum Direction {
Up,
Down,
Left,
Right
} function changeDirection(direction: Direction) {} changeDirection(Direction.Left)

枚举的功能类似于字面量类型+联合类型组合的功能,也可以表示一组明确的可选值。

枚举:定义一组命名常量。它描述一个值,该值可以是这些命名常量中的一个。

解释:

\1. 使用 enum 关键字定义枚举。

\2. 约定枚举名称、枚举中的值以大写字母开头。

\3. 枚举中的多个值之间通过 ,(逗号)分隔。

\4. 定义好枚举后,直接使用枚举名称作为类型注解。

可以直接使用 . 来访问枚举中的成员

数字枚举 字符串枚举

枚举是 TS 为数不多的非 JavaScript 类型级扩展(不仅仅是类型)的特性之一。

因为:其他类型仅仅被当做类型,而枚举不仅用作类型,还提供值 (枚举成员都是有值的)。

也就是说,其他的类型会在编译为 JS 代码时自动移除。但是,枚举类型会被编译为 JS 代码

enum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}

var Direction;
(function (Direction) {
Direction["Up"] = "UP";
Direction["Down"] = "DOWN";
Direction["Left"] = "LEFT";
Direction["Right"] = "RIGHT";
})(Direction || (Direction = {}));

说明:枚举与前面讲到的字面量类型+联合类型组合的功能类似,都用来表示一组明确的可选值列表。

一般情况下,推荐使用字面量类型+联合类型组合的方式,因为相比枚举,这种方式更加直观、简洁、高效。

any类型

原则上不推荐使用any类型这会让 TypeScript 变为 “AnyScript”(失去 TS 类型保护的优势)。

因为当值的类型为 any 时,可以对该值进行任意操作,并且不会有代码提示

let obj: any = { x: 0 }

// 访问不存在的属性 或者 赋值
// obj.aaa
// obj.aaa = 10 // 当作函数调用
// obj() // 赋值给其他类型的变量
// let n: number = obj // -- // let a
// a = 1
// a = ''
// a() // function add(num1, num2) {}
// add(1, 2)
// add(1, '2')
// add(1, false)

解释:以上操作都不会有任何类型错误提示,即使可能存在错误!

尽可能的避免使用 any 类型,除非临时使用 any 来“避免”书写很长、很复杂的类型!

其他隐式具有 any 类型的情况:1 声明变量不提供类型也不提供默认值 2 函数参数不加类型。

注意:因为不推荐使用 any,所以,这两种情况下都应该提供类型!

unknown与any

unknown只霍霍自己 赋值给别人是不行的 而any只要跟他沾边都会被霍霍都变成any

unknown就是个类型安全的any 赋值给别人前必须做判断

let e: unknown = 'str';
let s: string;
//unknown 赋值给别人需要先判断类型
if (typeof e === "string") {
s = e;
}
//或者类型断言
s = e as string;
s = <string>e;

联合类型

let a = "male" | "female"
a = "male";
a = "female";

typeof

void never

主要用于函数返回值的确定

function fn(num): void {
if (num>0) {
return; //不应有返回值
} else {
return undefined;
}
}
function fn2(): never{
throw new Error("出错了");//就是执行不完 一定会出错
}

object 与函数结构的类型声明

一般是不用object 限制太宽泛了

let a1: object;
a1 = {}
a1 = function () { };
//用于指定哪些属性
let b1: { name: string, age?: number }//加上问好表示属性可选
b1 = { name: '孙悟空' }
let c1: { name: string, [propName: string]: any }// [propName: string]: any表示可以有任意类型的属性
c1 = { name: "猪八戒", age: 18, gender: "male" }
//定义函数的参数结构 的类型声明
let d1: (a: number, b: number) => number;
d1 = function (a: number, b: number) { return a + b; };

array

//数组
let e1: string[];//表示字符串数组
e = ['a', 'b', 'c', 'd'];
let f1: number[];
let g1: Array<number>;

元组

长度固定的数组

//元组
/**
* 语法: [类型,类型,类型]
*/
let h1: [string, string, number];
h1 = ["hello", "world", 123];

或 | 和 与&


// | 表示或 & 表示且 let j1: { name: string } & { age: number }
j1={name: "孙悟空",age:18}

编译选项

tsc app.ts -w

-w watch模式 只监视app.ts

使用tsc 编译此项目下的全部ts文件 前提是得由tsconfig.json文件 即使这个文件为空json也会按照默认的选项来编译!

webpack打包TS

package.json 需要哪些包

{
"name": "ts-webpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"start": "webpack serve --open "
},
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.18.13",
"@babel/preset-env": "^7.18.10",
"babel-loader": "^8.2.5",
"clean-webpack-plugin": "^4.0.0",
"core-js": "^3.24.1",
"html-webpack-plugin": "^5.5.0",
"ts-loader": "^9.3.1",
"typescript": "^4.7.4",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.10.0"
}
}

webpack.config.js 定义打包的方式

//引入路径包
const path = require("path");
//引入一个插件包
const HTMLWebpackPlugin = require("html-webpack-plugin"); //引入clean插件
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
//添加模式
mode: "development",
//指定入口文件
entry: "./src/index.ts",
//指定打包文件所在目录
output: {
//指定目录
path: path.resolve(__dirname, "dist"),
//指定名字
filename: "index.js",
//配置环境兼容问题
environment: {
arrowFunction:false
}
},
//指定打包时要用到的模块
module: {
rules: [
{
//test指定的是规则生效的文件
test: /\.ts$/, //匹配以ts结尾的文件
//use 要使用的loader 数组中的内容从后往前执行
use: [
{
//设置加载器
loader: "babel-loader",
//设置babel
options: {
//设置预定义的环境
presets: [
[
//指定环境的插件
"@babel/preset-env",
//配置信息
{
//要兼容的默认浏览器
targets: {
//浏览器版本
"chrome": "58",
"ie":"11"
},
//指定corejs的版本
"corejs": "3",
//使用corejs的方式
"useBuiltIns": "usage"
}
]
]
},
},
"ts-loader",
],
//exclude 排除哪些文件
exclude: /node-modules/,
},
],
},
//配置webpack的插件
plugins: [
new CleanWebpackPlugin(),
new HTMLWebpackPlugin({
// title: "这是一个自定义的title",
template: "./src/index.html",
}),
],
//用来设置引用模块
resolve: {
extensions: [".ts", ".js"],
},
};

tsconfig.json ts的编译方式

{
"compilerOptions": {
"module": "ES2015",
"target": "ES2015",
"strict": true
}
}

//使用class关键字来定义一个类
/**
* 属性
* 方法
*/
class Person{
//实例属性
name: string = "孙悟空";
//在属性前加关键字static可以定义类属性(静态属性)即不需要创建实例就可访问的属性
static age: number = 18;
//只读属性
readonly gender: string = "male"; //实例方法
say() {
console.log('hello')
}
//静态方法
static run() {
console.log('run')
} }
const per = new Person();
console.log('per.name', per.name);
console.log('per', per);
per.say();
console.log('Person.age', Person.age)
Person.run();

构造函数与this

class Dog{
name: string;
age: number;
//构造函数
constructor(name: string, age: number) {
console.log('构造函数执行了',this)
this.name= name
this.age= age
} bark() {
console.log('wangwangwang')
}
}
const dog = new Dog('xiaohei',4);
console.log('dog',dog)

类的继承

(() => {
class Animal {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`${this.name}sayHello`);
}
} class Dog extends Animal {
sayHello(): void {
console.log("wangwangwang"); //子类覆盖掉父类的方法的形式叫重写
}
} class Cat extends Animal {
run() {
console.log(`${this.name}run`);
}
}
const dog = new Dog("旺财", 5);
const cat = new Cat("咪咪", 3);
console.log("cat", cat);
console.log("dog", dog);
dog.sayHello();
cat.sayHello();
cat.run();
})();

super

(() => {
class Animal {
name: string; constructor(name: string) {
this.name = name; }
sayHello() {
console.log(`${this.name}sayHello`);
}
} class Dog extends Animal {
age: number;
constructor(name: string, age: number) {
super(name);//必须先调用父类的构造函数
age = this.age;
} sayHello(): void {
super.sayHello(); //super表示当前类的父类
}
} const dog = new Dog('旺财',1);
dog.sayHello();
})();

抽象类

(() => {
abstract class Animal {
//我们不希望直接用Animal来创建实例,我们只需要让它是一个超类 用来被继承
//所以我们给它加上abstract 那么这个类就只能被继承 不能用它创建实例
//抽象类可以添加抽象方法
name: string; constructor(name: string) {
this.name = name;
}
//抽象方法只能在抽象类里定义 抽象方法没有方法体
//子类必须对抽象方法进行重写
abstract sayHello(): void;
} class Dog extends Animal {
//非抽象类继承抽象类 必须重写父类中的抽象方法
sayHello(): void {
console.log("汪汪汪");
}
} const dog = new Dog("旺财");
dog.sayHello();
})();

接口

(() => {
/**
* 对于类型声明(类型别名) 只能声明一次
*
* 对于接口 可以重复声明 多次声明那么创建的实例应把接口中的定义的都实现
* 接口可以限制类的结构
* 接口只定义类的结构不定义类的实际值
* 接口的所有方法都是抽象方法
*
*
*
*/
//描述一个对象的类型 类型别名
type myType = {
name: string;
age: number;
};
let obj: myType = {
name: "sss",
age: 1,
}; /**
* 接口用来定义一个对象的结构
* 用来定义一个类中应该包含哪些属性和方法
*/
interface myInterface {
name: string;
age: number;
}
interface myInterface {
gender: string;
sayHello(): void;
} let obj1: myInterface = {//当作类型使用
name: "aaa",
age: 2,
gender: "male",
sayHello() {
console.log("hello");
},
}; //实现接口
class Myclass implements myInterface {
name = '孙悟空';
age = 18;
gender = 'male';
sayHello() {
console.log("嘿嘿")
}
}
})();

属性的封装

private getter setter

(() => {
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
} let per = new Person("孙悟空", 18);
console.log("per", per);
per.name = "猪八戒";
per.age = -18;
console.log("per", per); //可以任意修改 年龄能有负数嘛?
/**
* 上面的属性是在对象中设置的,属性可以任意的被修改
* 属性可以任意被修改将会导致对象中的数据会变得非常不安全
*/
class Animal {
/**q
* 可以在属性前添加修饰符
*/
public name: string; //公共属性可以在任意位置(访问)更改 默认就是public
private age: number; //私有属性 只能在类内部(访问)修改
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
//getter 添加方法让私有属性可以在外部访问
getAge() {
return this.age;
}
//setter 设置属性
setAge(value: number) {
if (value > 0) {
this.age = value;
}
}
}
let dog = new Animal("旺财", 2);
console.log("dog", dog);
console.log("dog.getAge()", dog.getAge());
dog.setAge(-8);
console.log("dog", dog); //改不了
})();

protected 与 constructor 语法糖

(() => {
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
} let per = new Person("孙悟空", 18);
console.log("per", per);
per.name = "猪八戒";
per.age = -18;
console.log("per", per); //可以任意修改 年龄能有负数嘛?
/**
* 上面的属性是在对象中设置的,属性可以任意的被修改
* 属性可以任意被修改将会导致对象中的数据会变得非常不安全
*/
class Animal {
/**q
* 可以在属性前添加修饰符
*/
public _name: string; //公共属性可以在任意位置 包括子类 (访问)更改 默认就是public
private _age: number; //私有属性 只能在类内部(访问)修改
//protected 受保护的属性,只能在当前类和当前类的子类中访问
constructor(name: string, age: number) {
this._name = name;
this._age = age;
}
// //getter 添加方法让私有属性可以在外部访问
// getAge() {
// return this.age;
// }
// //setter 设置属性
// setAge(value: number) {
// if (value > 0) {
// this.age = value;
// }
// } //ts中设置获取属性 设置属性 的方法 不会改变访问数据的方法
/**
* 不是特别复杂的修改时 一般用不到
*/
get age() {
return this._age;
}
set age(value: number) {
if (value > 0) {
this._age = value;
}
}
}
let dog = new Animal("旺财", 2);
// console.log("dog", dog);
// console.log("dog.getAge()", dog.getAge());
// dog.setAge(-8);
console.log("dog.age", dog.age);
// console.log("dog", dog); //改不了
dog.age = 8;
console.log("dog", dog); /**
* 语法糖
*/ class C {
//得用public
constructor(public name: string, public age: number) {}
}
let c = new C("666", 6);
console.log("c", c);
})();

泛型

(() => {
function fn(a: any): any {
return a;
}
/**
* 在定义函数或是类时遇到类型不明确的 可以使用泛型
*
*/
function fn1<T>(a: T): T {
//我不知道a到底是是么类型但是我知道 返回值和入参的类型时相同的
return a;
}
fn1(10); //自动推断
fn1<string>("test"); //类型断言 function fn2<T, K>(a: T, b: K): T {
console.log("b", b);
return a;
}
fn2(123, "test");
fn2<number, string>(333, "test"); interface Test {
length: number;
}
//泛型T得是Test的实现类(子类)
function fn3<T extends Test>(a: T): number {
return a.length;
}
fn3([1, 2, 2]); //传入的参数的类型得是Test接口的实现类
})();

仓库地址:https://gitee.com/bbigger004/tslearn.git

TS学习笔记的更多相关文章

  1. TS学习笔记----(一)基础类型

    布尔值: boolean let isDone: boolean = false; 数字: number 和JavaScript一样,TS里的所有数字都是浮点数. 支持十进制和十六进制字面量,TS还支 ...

  2. ts 学习笔记-基础篇

    目录 基础 原始数据类型 布尔值 数字 字符串 空值 Null 和 Undefined 任意值 类型推论 联合类型 接口 数组 函数 类型断言 申明文件 什么是申明文件 三斜线指令 第三方声明文件 内 ...

  3. ts 学习笔记 - 泛型

    目录 泛型 举个栗子 泛型约束 多个参数时也可以在泛型约束中使用类型参数 泛型接口 泛型类 泛型参数的默认类型 泛型 泛型(Generics)是指在定义函数.接口或者类的时候, 不预先指定其类型,而是 ...

  4. ts 学习笔记 - 类

    目录 类 类的概念 类的用法 属性和方法 类的继承 存取器 静态属性 Typescript 中的用法 抽象类 类的类型 类与接口 类实现接口 接口继承接口 接口继承类 混合类型 类 类的概念 类 (c ...

  5. ts 学习笔记 - 进阶篇 1

    目录 进阶 类型别名 字符串字面量类型 元祖 例子 越界的元素 枚举 手动赋值 常数项和计算所得项 常数枚举 外部枚举 进阶 类型别名 类型别名用来给一个类型起个新名字 type Name = str ...

  6. Ionic2学习笔记(9):访问本地设备

    作者:Grey 原文地址: http://www.cnblogs.com/greyzeng/p/5559927.html               Ionic2提供了访问本地设备的方法,但是需要安装 ...

  7. Ionic2学习笔记(8):Local Storage& SQLite

    作者:Grey 原文地址: http://www.cnblogs.com/greyzeng/p/5557947.html              Ionic2可以有两种方式来存储数据,Local S ...

  8. Ionic2学习笔记(7):Input

    作者:Grey 原文地址: http://www.cnblogs.com/greyzeng/p/5554610.html           我们先来看一个简单的输入用户名和密码点击登录的界面:   ...

  9. Ionic2学习笔记(6):Navigation

    作者:Grey 原文地址: http://www.cnblogs.com/greyzeng/p/5551535.html           Ionic2中创建一个页面很方便,在页面之间相互切换也很方 ...

随机推荐

  1. cudaMemcpy cudaMalloc

    cudaMemcpy有四种类型:HostToHost, DeviceToHost, HostToDevice, DeviceToDevices 现在我有两个指针:h_ptr, d_ptr,分别指向ho ...

  2. 【神经网络】丢弃法(dropout)

    丢弃法是一种降低过拟合的方法,具体过程是在神经网络传播的过程中,随机"沉默"一些节点.这个行为让模型过度贴合训练集的难度更高. 添加丢弃层后,训练速度明显上升,在同样的轮数下测试集 ...

  3. Ubuntu实现电商网站+Mysql主从复制+NFS

    Ubuntu实现电商网站+Mysql主从复制+NFS 1.环境准备 提前准备:Mysql8.0.30安装包.Mysql安装脚本.shopxo2.3.0安装包.DNS脚本 服务器 IP地址 作用 系统版 ...

  4. 【Azure 环境】把OpenSSL生产的自签名证书导入到Azure Key Vault Certificate中报错

    问题描述 通过本地生成的自签名证书导入到Azure Key Vault Certificate报错. 错误信息 the specified PEM X.509 certificate content ...

  5. 【笔记】CF1607F Robot on the Board 2 及相关

    题目传送门 记忆化搜索 首先,这题 \(10000\) 组 \(2000\times 2000\) 的数据直接爆搜肯定会超时.想到,如果一个点的答案已经被更新过,之后走到这个点能再多走的点也就确定了, ...

  6. 解决头部使用 position:fixed; 固定定位后遮住下方内容的问题

    1.在头部下面给一个空的 div 给这个div设置高度,把页面撑开,这种方法是让头部刚好遮住的是这个空div,把内容放出来. 但是这种方法需要一点点调试高度,所以不推荐. 2.把整个要使用 posit ...

  7. 深度学习之tensorflow2实战:多输出模型

    欢迎来到CNN实战,尽管我们刚刚开始,但还是要往前看!让我们开始吧! 数据集 链接:https://pan.baidu.com/s/1zztS32iuNynepLq7jiF6RA 提取码:ilxh,请 ...

  8. day21-web开发会话技术03

    WEB开发会话技术03 10.问题引出 问题引出 不同的用户登录网站后,不管该用户浏览网站的哪个页面,都可以显示登录人的名字,还可以随时去查看自己购物车中的商品,这是如何实现的呢? 也就是说,一个用户 ...

  9. 递归与Stream流转换

    目录 递归与Stream流转换 list转为类中一个属性为key,类实例为value的Map list单独取出对象中一个属性成为集合/数组 步骤:--在此只写service层代码 递归与Stream流 ...

  10. 论文复现|Panoptic Deeplab(全景分割PyTorch)

    摘要:这是发表于CVPR 2020的一篇论文的复现模型. 本文分享自华为云社区<Panoptic Deeplab(全景分割PyTorch)>,作者:HWCloudAI . 这是发表于CVP ...