概念:
- TypeScript的作者是安德斯·海尔斯伯格,C#的首席架构师。2012年10月,微软发布了首个公开版本的TypeScript,2013年6月19日,在经历了一个预览版之后微软正式发布了正式版TypeScript,是由微软开发的开源、跨平台的编程语言。
- TypeScript是为大型应用的开发而设计,并且可以编译为JavaScript。
- TypeScript 是 JavaScript 的一个超集,TypeScript扩展了JavaScript的语法,任何现有的JavaScript程序都可以运行在TypeScript环境中。也提供了类型系统和对 ES6+ 的支持
- TypeScript 是 JavaScript 的强类型版本。然后在编译期去掉类型和特有语法,生成纯粹的 JavaScript 代码。由于最终在浏览器中运行的仍然是 JavaScript,所以 TypeScript 并不依赖于浏览器的支持,也并不会带来兼容性问题。
类型
- any
// 表示任意类型的值, 如果声明变量不指定类型,则TS解析器会自动判断变量类型为 any(隐私any)
// 随意更改类型
let d
d = 10
d = 'string'
- unknown
// 表示未知类型的值
// 跟any一样
let e: unknown
e = 10
e = 'hello'
any跟unknown的区别:
let s: string
// d类型是any, 它可以赋值给任意变量,也就关闭了s的类型判断了,所以要避免
s = d
// 报错, unknown实际上是一个安全的any
// unknown的变量,不能直接复制给其他变量
// s = e
- 类型断言
/**
* 可以用来告诉解析器变量的实际类型
* 语法:
* 变量 as 类型
* <类型>变量
*/
s = e as string
s = <string>e
- void
// 没有值(undefined)
function show(): void {
return undefined || null
}
- never
function show1(): never {
throw new Error('报错了')
}
对象设置属性
- 可选属性
// {} 用来指定对象中可以包含哪些属性,
// 在属性名后面加个?,表示属性是可选的
let f: {
name: string,
age?: number,
readonly id: number
} // 有且只有name,age可选,其他不能
f = {
name: '1',
// age: 15 有也行无也行
id: 1 // 只能读不能更改值
}
- 自定义属性
// 至少有name属性
let g: {name: string, [protoName: string]: any}
g = {
name: "1",
demo: 2
}
函数结构体声明
/**
* 设置函数结构的声明:
* 语法: (形参:类型, 形参:类型....) => 返回值
*/
let h: (a: number, b: number) => number
h = (a: number, b: number) => {
return a + b
}
// 报错
// h = (a: string, b: number) => {
// return a + b
// }
数组类型声明
/**
* 数组类型声明:
* 类型[]
* Array<类型>
*/
let i: string[]
let j: number[]
let k: Array<number>
元祖
/**
* 元组:新增类型,元组就是固定长度的数组
* 语法: [类型, 类型, 类型...]
*/
// 只允许两个元素
let l: [number, string]
l = [1, 'str']
枚举类型
/**
* enum 新增类型 枚举
*
*/
enum Gender{
Male,
Female
}
let m: {name: string, gender: Gender}
m = {
name: 'lq',
gender: Gender.Male
}
console.log(m.gender === Gender.Male);
enum Demo{
one=11,
two,
three=21,
four
}
log:
Demo.one 11
Demo.two 12
Demo.three 21
Demo.fout 11
类型别名
// 类型的别名
type myType = 1 | 2 | 3 | 4
let n: myType
let o: myType
n = 3
接口
对象
interface UseObj {
name: string,
age?: number,
readonly id: number
}
let obj:UseObj = {
name: '林',
age: 11, // 可有可无
id: 10 // 只读不写
}
函数
interface UseFun {
(name: string, age: number): void
}
let fun:UseFun = (name, age) => {
console.log()
}
抽象类
(() => {
// 抽象类无法被new实例化
abstract class ParentClass{
name:string
constructor(name:string) {
this.name = name
}
// 定义一个抽象方法
// 抽象方法使用abstract开头,没有方法体
// 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
abstract sayHi():void
}
class ChildClass extends ParentClass{
age: number
constructor(name: string, age: number) {
super(name)
this.age = age
}
sayHi() {
console.log('11');
}
}
let p1 = new ChildClass('l1', 2)
// let p = new ParentClass('llq')
})()
接口
(function() {
// 定义类型
type MyInter1 = {
name: string,
age: number,
[prototype: string]: any
}
let p1: MyInter1 = {
name: 'lq',
age: 1
}
/**
*
* 定义接口
* 接口可以在定义类的时候限制类的结构
* 接口只定义对象的结构,而不考虑实际值
* 接口中所有的属性都不能有实际的值
* 在接口中的所有方法都是抽象方法
*/
interface MyInter {
name: string,
age: number,
sayHi(): void;
}
/**
*
* 定义类时, 可以使类去实现一个接口,
* 实现接口就是使类满足接口的要求
* */
class Myclass implements MyInter {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
sayHi(): void {
console.log(1);
}
}
})()
interface和type的异同
interface侧重于描述数据结构
type(类型别名)侧重于描述类型
type age = number
type dataType = number | string
属性的封装
01
(function() {
class Person{
/**
*
* public 修饰的属性可以在任意位置访问(修改),包括子类, 默认值
*
* private 私有属性,私有属性只能在类内部访问(修改),不能被子类访问
* 通过在类中添加方法使得私有属性可以被外部访问
*
* protected 保护属性,只能在当前类和子类中被访问
*/
private name: string
constructor(name: string) {
this.name = name
}
getName() {
return this.name
}
setName(value: string) {
if(value !== 'moy') {
this.name = value
}
}
}
let p = new Person('lq')
console.log(p.getName);
p.setName('lq1')
})()
02
(function() {
class Person{
private _name: string
constructor(name: string) {
this._name = name
}
/**
*
* getter方法获取属性
* setter方法设置上属性
* - 它们被称为属性的存取器
*/
// TS设置中设置getter方法的方式
get name() {
return this._name
}
set name(value: string) {
this._name = value
}
}
let p = new Person('lq')
console.log(p.name);
p.name = 'lq1'
})()
03
(function () {
class Person{
name: string
constructor(name: string) {
this.name = name
}
}
//---------------- 等价于 ------------------
class Person1{
// 直接把属性定义在构造函数中
constructor(public name: string) {}
}
let p1 = new Person1('lq')
console.log(p1);
}
)()
泛型
/**
*
* 在定义函数或者类时,如果遇到类型不明确就可以使用泛型
*
*/
function fn<T>(a: T): T{
return a
}
// 可以直接调用具有泛型的函数
let result1 = fn(10) // 不指定泛型,TS可以自动对类型进行推断
let result2 = fn<string>('lq') // 指定泛型
// -----------------------------------------
function fn1<T, K>(a: T, b: K): T{
console.log(b);
return a
}
let result3 = fn1<string, number>('lq', 12)
// -----------------------------------------
interface Inter{
length: number
}
// T extends Inter 表示泛型T必须是Inter实现类(子类)
function fn3<T extends Inter>(a: T): number {
return a.length
}
let result4 = fn3({
length: 3
})
// -----------------------------------------
class Myclass<T> {
name: T
constructor(name: T) {
this.name = name
}
}
const mv = new Myclass<string>('lq')