TypeScript基础

简介:
TypeScript是微软开发的⼀个开源的编程语⾔,通过在JavaScript的基础上添加静态类型定义构建⽽成。通过TypeScript编译器或Babel转译为JavaScript代码,可运⾏在任何浏览器,任何操作系统。

1. 环境搭建

npm install typescript -g
tsc -v
tsc --init

2. 类型

静态类型检查,在编写或编译阶段就排查出相应的错误,规避js默认的隐式转换带来的困扰

let str:string = 'hello';
let num:number = 123;
let flag:boolean = true;
let undef:undefined = undefined;
let nul:null = null; 
export default {} //模块导出,局部变量避免提示重名错误

2.1 数组、元组和对象

//限制类型的数组
let arr1:number[]=[1,2,3]
let arr2:Array<number>=[1,2,3] //泛型
let arr3:(number|string|boolean)[]=['hello',true,12] 
//不限制类型的数组
let arr4:any[]=[1,'hello']
let arr5:Array<any>=[1,'hello']
//数组对象
let arr6:object[]=[{x:12,y:24}] //不建议
type People = {name:string,age:number} //建议
interface People2 {name:string,age:number} //更建议
let arr7:People2[]=[{name:'xx',age:18}]
//元组类型实际只是固定了长度和每个元素类型的数组,可以使用数组的方法。
//但由于类型限制了长度和具体的元素类型,所以部分功能又受到限制
let arr:[number,string]=[1,'hello'] 
arr.push(1)
// arr[0]='1'
// arr[2]=1  //ts2.7后访问一个越界的元素 error! 中文官网尚未更新
console.log(arr)

2.2 函数、枚举

// 带参数⽆返回值
function people(name:string,age:number):void{
    console.log(name,age)
}
// 带参数有返回值
function people2(name:string,age:number):string{
    return name
}
people('xx',18)
let res = people2('xx',18) 

使用枚举类型可以为一组数值赋予友好的名字,通常描述常量。 每个枚举成员都带有一个值,它可以是 常量或 计算出来的
默认情况下,从0开始为元素值,手动赋值,可以由枚举的值得到它的名字

//数字枚举
enum Status{
    Success=100,
    Error
}
//计算的枚举
enum FileAccess {
    nameLen = "前端娱乐圈".length, 
    num = Math.random() * 100  
}
//比方为了节俭额定的开销和性能,可以使用 const枚举
//不同于常规的枚举,它们在编译阶段会被删除
//成员只能是常量枚举表达式,不能够应用计算值
const enum State{ //只可以正向映射
    Success=100,
    Error
}
let code:Status=Status.Error //正向映射
let name:string=Status[101] //反向映射,不会为字符串枚举成员生成反向映射
console.log(code,name) // 101 'Error'
export default {}

2.3 any、unknown

any 表示任意类型,设置为any相当于对该变量关闭了TS的类型检测,不建议使用

let a;//隐式any // 等于let a:any;(显示any)
a=1;
a='hello';
let b=18; //隐式number
b=a; // a是any类型,它可以赋值给任意变量 此时b的类型也被影响了

与any相反,unknown必须进行类型检查之后才能操作,会使代码更加安全

let point:unknown = 3.1415
//let point2 = point.toFixed(2) //error

使unknown类型能正常使用
let point:unknown = 3.1415
//1. 收窄类型,让ts编译器"看到"并且"相信"你的操作是合法安全的
if(typeof point === 'number'){
    let point2 = point.toFixed(2)
}
//2. 类型断言 (当你在TypeScript里使用JSX时,只有 as语法断言是被允许的)
let point3 = (point as number).toFixed(2) 
let point4 = (<number>point).toFixed(2)

2.4 void、never

一个函数如果返回值是void类型,返回值只能是null或undefined(函数的默认返回值undefined)

// ok
const func:()=>void = () => {}

never表示的是那些永不存在的值的类型,比如一个总是会抛出错误的函数,或者是一个从来不会有返回值的函数
// ok
const func:(msg:string)=>never = (msg) => {
    throw new Error(msg)
}
//ok
const hello:()=>never = () => {
    while(true){ console.log('hello') }
}
// error
const func:()=>never = () => {}

3. 接口

interface

interface People{
    name:string,
    age:number
}
function func():People{
    return {name:'xx',age:18}
}
let res = func()
export default{}

3.1 继承接口

interface People{
    name:string,
    age:number
}
interface Teacher extends People{
    job:string
}
function func():Teacher{
    return {name:'xx',age:18,job:'teacher'}
}
let res = func()
export default{}

3.2 |、?、!、类型断言

interface People{
    name:string,
    age:number|string, //| 联合类型
    gender?:string //? 可选属性
}
//! 使null和undefined类型可以赋值给其他类型并通过编译
function demo(param:People):People{
    let a:number; 
    a=param.age!;
    return param
} 
demo({name:'xx',age:18})  
export default{}
//类型断言尽量不要滥用,只有当一些复杂情况,TS 不能推断出类型的时候,用类型断言
//类型断言不是类型转换,它不会真的影响到变量的类型
function demo2(param:string|number):void{ 
    //let len = param.length //error “number”上不存在属性“length”
    let len = (param as string).length
    console.log(len)
}

3.3 只读

//只读属性,在对象创建结束后无法修改其值
interface Point {
    readonly x: number;
    readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!

3.4 索引签名

可以用字符串访问 TS中的对象,用来保存对其他对象的引用,所有成员都必须符合索引签名。

interface People{
    name:string;
    age:string;
    [prop:string]:string //扩展原对象必要内容外的属性类型
}
let obj: People = {
    name:'xx',
    age:'18',
    gender:'女'
}
console.log(obj['gender'])
export default {}

3.5 interface和type

接口主要用于类型检查,它只是一个结构契约,定义了具有相似的名称和类型的对象结构。除此之外,接口还可以定义方法和事件。
类型别名有时和接口很像,但还可以定义基础类型、联合类型或交叉类型。 建议优先选择接口,接口满足不了再使用类型别名

1. Object / Function

两者都可以用来描述对象或函数的类型

//interface 
interface Point {
  x: number;
  y: number;
}
interface SetPoint {
  (x: number, y: number): void;
}
//type 
type Point = {
  x: number;
  y: number;
};
type SetPoint = (x: number, y: number) => void;

2. Other Types

type 声明可以声明任何类型,包括基础类型、联合类型或元组。

//基本类型
type Person = string;
//联合类型
type Point = PointX | PointY;
//元组
type Data = [number, string]
//可以获取 typeof 返回的值作为类型
let div = document.createElement("div");
type B = typeof div; 

3. Extend

两者都可以扩展,interface使用extends,type 使用交叉类型&,
此外,接口和类型别名不是互斥的。接口可以扩展类型别名,反之亦然

/

/interface extends interface
interface People{ name:string }
interface Teacher extends People{ job:string }
//interface extends type
type Person = { name: string };
interface User extends Person {
  age: number;
}

//type & type
type People={name:string};
type Teacher=People & {age:number}
//type & interface
interface Person {
  name: string;
}
type User = { age: number } & Person;

4. Declaration merging

定义两个相同名称的接口会合并声明,定义两个同名的 type 会出现异常

interface People{
  name: string;
}
interface People{
  age: number;
}
// 合并为:interface People { name: string age: number}

type User = {
  name: string;
};
type User = {
  age: number;
};
// 声明重复报错:标识符“User”重复。

在 type 或 interface 中使用函数声明

保持一致性,类型/接口的所有成员都通过相同的语法定义
–strictFunctionTypes 在比较函数类型时强制执行更严格的类型检查,但第一种声明方式下严格检查不生效。

interface Counter {
  start: (value: number) => string
}
//建议为
interface Counter {
  start(value: number): string
}

4. 泛型

泛型表示的是一个类型在定义时并不确定,需要在调用的时候才能确定的类型

//第一种写法
function getId<T>(arg:T): T {
  return arg
}
//第二种写法
const getId2: <T>(arg:T)=>T = arg => {
  return arg
}
let res = getId('12');
let res2 = getId(12)
export default {}

4.1 泛型接口

//第一种写法
interface Generic{
    <T>(arg:T):T
}
let getArg:Generic=function func<T>(arg:T):T{
    return arg
}
getArg<string>('hello')
//第二种写法
interface Generic2<T>{
    (arg:T):T
}
let getArg2:Generic2<string>=function func2<T>(arg:T):T{
    return arg
}
getArg2('helloa')
export default {}

5. React

5.1 函数式组件

1. 声明方式

推荐React.FC

interface IProps { 
  title?: string
}
const PlsModal: React.FC<IProps> = function(props) (
  const { title='提示' } = props;  //推荐使用默认参数值来代替defaultProps
  return (
      <div>{ title }</div>
  )
)
export default PlsModal;

2. useState

大部分情况下,TS 会自动为你推导 state 的类型:

// visible会推导为boolean类型
const [visible, setvisible] = React.useState(false)
// obj会自动推导为类型: {name: string}
const [obj] = React.useState({ name: 'sj' })

如果初始值为 null 需要显示的声明类型
type User = {
  name: string
  age: number
}
const [user, setUser] = React.useState<User | null>(null)

3. useRef

当初始值为 null 时,有两种创建方式:

//ref1.current 是只读的
const ref1 = React.useRef<HTMLInputElement>(null)
//ref2.current 是可变的
const ref2 = React.useRef<HTMLInputElement | null>(null)

//获取ScrollTop 
const ScrollTop = Math.ceil(ref2.current?.scrollTop as number);
//修改ScrollTop 
const _curr = aggressionsRef.current as HTMLInputElement;
_curr.scrollTop = 0;

5.2 Class组件

interface IProps { 
  title?: string
}
interface IState { 
  str?: string
}
class PlsModal extends React.PureComponent<Iprops>{
    state: IState = {
        str:''
    };
    render() {
        return (
            <div>{this.props.title}</div>
        )
    }
} 
export default PlsModal;

5.3 常用 React 属性类型

export declare interface AppBetterProps {
  children: React.ReactNode // 一般情况下推荐使用,支持所有类型 Great
  functionChildren: (name: string) => React.ReactNode
  style?: React.CSSProperties // 传递style对象
  submitForm?: (e: React.FormEvent) => void //form表单event的类型
  changeInput?: (e: React.ChangeEvent<HTMLInputElement>) => void //输入框onChange事件触发的event类型
  onClick:(e:React.MouseEvent<HTMLDivElement>) => void //div标签的事件
}

export declare interface AppProps {
  children1: JSX.Element //不支持数组
  children2: JSX.Element | JSX.Element[] //不支持字符串
  children3: React.ReactChildren // 忽略命名,不是一个合适的类型,工具类类型
  children4: React.ReactChild[] // 很好
  children: React.ReactNode // 支持所有类型 推荐使用
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值