TS学习和在react中的简单应用
1. ts基础
1.1 ts基本类型
//js原始类型:number/string/boolean/null/undefined/symbol
//ts新增any-任意类型
//1-
var name:string | number;
//string或是number类型
//多种数据类型中的一种,TS中称为联合类型
//2-类型别名
type mytype = string | number;
let age:mytype = 10;
1.2 数组
//1-已知数组的长度和类型:在TS中称为元组类型
//表示数组的每一项都是字符串,长度不固定
var arr1:string[] = ['1','2'];
//表示数组的每一项都是字符串或者数字,长度不固定
var arr2:(string | number)[] = [1,'2'];
var arr3:Array<string | number> = [1,'2'];
//2-表示数组只能是两项,第一项是字符串,第二项是数字,不能多,不能少
var arr: [string, number] = ['lala', 10]
1.3 对象
// 1- 对象类型
type o = {a:number,cb():void,list?:string[],[propName:string]:any}
let obj:o = {
a:0,
cb() {},
list:['1']
}
// 2- interface-在TS中称为接口,用来描述对象的形状
//表示必须有name是字符串类型,age是数字类型两个属性
//loaction属性中的“?”表示可有可无
//[propName:string]:any 可以有任意类型的属性
interface IObj {
name:string,
age:number,
location?:string,
// [propName:string]:any
}
var obj1:IObj = {
name:'lala',
age:10,
location:'1'
}
var obj1:IObj = {
name:'lala',
age:10,
}
var obj1:IObj = {
name:'lala',
age:10,
// a:1
}
//3-接口继承:如果两个接口有相同的属性方法时使用继承来实现复用
interface A {
a:string
}
interface B {
b:number
}
interface AB extends A,B{
ab:()=>void
}
let obj2:AB = {
a:'111',
b:222,
ab(){}
}
//4-对比:interface(接口)与type(类型别名)
//相同:都可以给对象指定类型
//不同:interface只能为对象指定类型,type可以为任意类型指定别名
export default {}
1.4 函数
//1-
//指定a,b形参类型分别为字符串和数字,必须有返回值,返回值类型为布尔和数字
//c旁的?表示这个参数可有可无
//没有返回值类型为void
// function fun1(a:string,b:number,c?:string):boolean | number{
// return b;
// };
// let fun1 =(a:string,b:number,c?:string):boolean | number =>{
// return b;
// };
let fun1:(a:string,b:number,c?:string) => boolean | number = (a,b,c) => {
return b;
};
// var myname:number = fun1('1',1) //不能将boolean | number的值赋值给数字类型的myname
fun1('1',2);
fun1('1',2,'3');
//2-
interface IFun{
(a:string,b:number,c?:string):boolean | number
};
var fun2:IFun = fun1;
//3-
interface Iobj{
name:string,
age:number,
getInfo?:(name:string)=>string
}
var obj:Iobj = {
name:'lala',
age:2,
getInfo:(name:string)=>name
}
1.5 class类
//1-
class Bus{
public name = 'lala';
private _list:any = [];
protected age = 10;
subscribe(cb:any){
this._list.push(cb);
};
dispatch(){
this._list.forEach((cb:any )=> {
cb&&cb();
});
}
}
class Child extends Bus{
getInfo(){
// console.log(this.name,this._list,this.age) //_list私有属性访问不到
}
}
var obj = new Bus();
// console.log(obj.name,obj._list,obj.age) //_list私有属性和age受保护属性访问不到
//2-
//该接口表示至少要有getName属性
// interface Ifun1{
// getName:()=>string,
// }
interface Ifun1{
getName():string
}
class A implements Ifun1{
a1(){
}
a2(){
}
getName(){
return 'AAA'
}
}
class B implements Ifun1{
b1(){
}
b2(){
}
getName(){
return 'BBB'
}
}
function init(obj:Ifun1){
obj.getName();
}
var objA = new A();
var objB = new B();
init(objA);
init(objB);
console.log(objA)
//-3 接口还可以通过extends 继承
interface IFun2 extends Ifun1{
allInfo:{name:string}
}
class C implements IFun2{
allInfo = { name:'lala' };
getName = ()=> 'CCC'
}
1.6 枚举enum
1.7 typeof
let obj1 = {
name:'lala',
age:19,
}
let obj2:(typeof obj1) = {
name:'xiaoming',
age:10,
}
1.8 TS中的泛型
//TS中的泛型 https://blog.csdn.net/weixin_44761091/article/details/124017662
//1. 泛型用法------------------------------------------------------------------------------------------
//1.1 在函数中使用泛型
function test <T> (arg:T):T{
console.log(arg);
return arg;
}
test<number>(111);// 返回值是number类型的 111
test<string | boolean>('hahaha')//返回值是string类型的 hahaha
test<string | boolean>(true);//返回值是布尔类型的 true
//1.2 在接口中使用泛型
interface Search {
<T,Y>(name:T,age:Y):T
}
let fn:Search = function <T, Y>(name: T, id:Y):T {
console.log(name, id)
return name;
}
fn('li',11);//编译器会自动识别传入的参数,将传入的参数的类型认为是泛型指定的类型
//1.3 在类中使用泛型
class Animal<T> {
name:T;
constructor(name: T){
this.name = name;
}
action<T>(say:T) {
console.log(say)
}
}
let cat = new Animal('cat');
cat.action('mimi')
//2. 泛型约束-------------------------------------------------------------------------------------------------
//2.1 使用接口约束泛型
interface Person {
name:string;
age:number;
}
function student<T extends Person>(arg:T):T {
return arg;
}
// student({name:'lili'});//报错:类型 "{ name: string; }" 中缺少属性 "age",但类型 "Person" 中需要该属性
// student({ name: "lili" , age:'11'});//报错不能将类型“string”分配给类型“number”
student({ name: "lili" , age:11});
//2.2 数组泛型
let arr:Array<number> =[1,2,3]
// let arr:number[]=[1,2,3]
//3. 泛型工具类型--------------------------------------------------------------------------------------------------
//3.1 Partial
//partial<T>的作用就是将某个类型中的属性全部变为可选项?
interface Person {
name:string;
age:number;
}
function person<T extends Person>(arg: Partial<T>):Partial<T> {
return arg;
}
person({name:'hua'})
person({age:0})
person({})
//3.2 Record
//type Record<K extends keyof any, T>的作用是将中的类型转换对象属性,T转为对象的属性值
//https://blog.csdn.net/qq_36503569/article/details/119383782
type key ='home'|'about'|'other';
interface value {
title:string
}
const data:Record<key,value> = {
home:{title:'home'},
about:{title:'about'},
other:{title:'other'},
}
let a:{[propName:symbol]:string} = {};
let name1 = Symbol('name');
let name2 = Symbol('name')
// a.name = 'lili';//报错不能ongoing.访问
a[name1] = 'lucy';
// console.log(a);//{Symbol(name1): 'lucy'}
// console.log(a[name1]);//lucy
// console.log(name1 === name2)//false
let title1 = Symbol.for("天天向上");
let title2 = Symbol.for("天天向上");
// console.log(title1,title2)//Symbol(天天向上)
// console.log(title1 === title2)//true
// console.log(Symbol.keyFor(title1)); // 天天向上
// console.log(Reflect.ownKeys(a))//[Symbol(name)]
// console.log(Reflect.ownKeys([]))//['length']
// console.log(Reflect.ownKeys(['w']))//['0', 'length']
//3.3 Pick
// Pick<T, K>
// K应为“keyof T”中的所包含的子类型
interface Todo {
title:string,
desc:string,
time:string
}
//表示对象必须有且只有title和time两个属性类型
//K不能为'title'|'time'|'a',eyof T中不含a类型
type TodoPreview = Pick<Todo, 'title'|'time'>;
const todo: TodoPreview ={
title:'吃饭',
time:'明天',
}
//3.4 Exclude
// Exclude<T,U>的作用是将某个类型中属于另一个类型的属性移除掉
type T0 = Exclude<"a" | "b" | "c", "a">; // 去除"a",得到b" | "c"
const t:T0 ='b';
//2.5 ReturnType
// returnType<T>的作用是用于获取函数T的返回类型
type T00 = ReturnType<() => string>; // string
type T1 = ReturnType<(s: string) => void>; // void
type T2 = ReturnType<<T>() => T>; // {}
type T3 = ReturnType<<T extends U, U extends number[]>() => T>; // number[]
type T4 = ReturnType<any>; // any
type T5 = ReturnType<never>; // any
// type T6 = ReturnType<string>; // 报错
// type T7 = ReturnType<Function>; // 报错
2. class+ts
2.1 state
import React, { Component,createRef } from 'react'
interface iState {
text:string,
// list:string[]
list:Array<string>
}
export default class App extends Component<any,iState> {//<约定属性,约定状态>
state ={
text:'',
list:[]
}
//HTMLInputElement指定input元素类型
//HTMLDivElement指div元素类型
myref = createRef<HTMLInputElement>();
render() {
return (
<div>
{/* <input type="text" value={this.state.text} onChange={
(e)=>{
this.setState({text:e.target.value})
}
}/>
{this.state.text} */}
<input ref={this.myref}/>
<button onClick={()=>{
// as是断言的一种方式,我断定这个类型是什么
//as any也不会报错
console.log((this.myref.current as HTMLInputElement).value)
this.setState({
text:(this.myref.current as HTMLInputElement).value,
list:[...this.state.list,(this.myref.current as HTMLInputElement).value]
});
}}>点我{this.state.text}-{this.state.list.toString()}</button>
</div>
)
}
}
2.2 props
import React, { Component } from 'react'
export default class App extends Component{
state = {
show:false
}
render() {
return (
<div>
app
<Navbar title="首页" cb={()=>{
this.setState({show:!this.state.show})
}}/>
{this.state.show && <Sidebar/>}
</div>
)
}
}
interface iProps {
title?:string,
cb:()=>void
}
class Navbar extends Component<iProps,any> {
render(){
return (
<div>
Navbar-{this.props.title}
<button onClick={()=>{
this.props.cb();
}}>add</button>
</div>
)
}
}
class Sidebar extends Component {
render(){
return (
<div>
Sidebar
</div>
)
}
}
3. function+ts
3.1 state
import React,{useState,useRef} from 'react'
export default function App() {
const [name] = useState<string>('lala');
const [list,setList] = useState<string[]>([]);
const myref = useRef<HTMLInputElement>(null);
return (
<div>
name-{name}
<input ref={myref} />
<button onClick={()=>{
console.log((myref.current as HTMLInputElement).value)
setList([...list,(myref.current as HTMLInputElement).value])
}}>add</button>
{list.toString()}
</div>
)
}
3.2 props
import React,{useState} from 'react'
export default function App() {
const [show,setShow] = useState(false);
return (
<div>
<Navbar title="lala" cb={()=>{
setShow(!show)
}} a="1"/>
{show && <Sidebar/>}
</div>
)
}
interface iProps {
title?:string,
cb():void,
[propName:string]:any
}
// function Navbar (props:iProps){
// return (
// <div>
// Navbar-{props.title}
// <button onClick={()=>{
// props.cb();
// }}>add</button>
// </div>
// )
// }
const Navbar:React.FC<iProps> = (props)=>{
return (
<div>
Navbar-{props.title}
<button onClick={()=>{
props.cb();
}}>add</button>
</div>
)
}
function Sidebar(){
return <div>Sidebar</div>
}
4. router
类型RouteComponentProps防止props中history报错
import React, { Component } from 'react'
import axios from 'axios'
import { RouteComponentProps } from 'react-router-dom'
interface IItem {
filmId:number,
name:string
}
//类型RouteComponentProps防止props中history报错
export default class Film extends Component<RouteComponentProps,any> {
state ={
list:[]
}
componentDidMount(): void {
axios({
url:"https://m.maizuo.com/gateway?cityId=110100&pageNum=1&pageSize=10&type=1&k=9261499",
method:'get',
headers:{
'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.1","e":"16745641013679850669801473","bc":"110100"}',
'X-Host': 'mall.film-ticket.film.list'
}
}).then(res=>{
this.setState({list:res.data.data.films})
})
}
render() {
return (
<div>
{
this.state.list.map((item:IItem) => {
return <li key={item.filmId} onClick={()=>{
this.props.history.push('/detail/'+item.filmId)
}}>{item.name}</li>
})
}
</div>
)
}
}
防止this.props.match.params.id报错
- 方法一:
RouteComponentProps对this.props.match做规范
IParam对this.props.match中的属性id做规范 - 方法二:
使用as断言(this.props.match.params as any).id
import React, { Component } from 'react'
import { RouteComponentProps } from 'react-router-dom'
interface IParam {
id:string
}
export default class Detail extends Component<RouteComponentProps<IParam>> {
render() {
return (
<div>
{/* 直接写id,会报错id属性不存在
解决方法一:用as any
解决方法二:IParam */}
{/* Detail-{(this.props.match.params as any).id} */}
Detail-{this.props.match.params.id}
</div>
)
}
}
5. redux
对prevState和action做规范
import {createStore} from 'redux'
interface iState {
show:boolean
}
interface iAction {
type:string,
payload?:any
}
const reducer = (prevState:iState={
show:true
},action:iAction)=>{
let newState = {...prevState};
switch(action.type){
case 'show':
newState.show = true;
return newState;
case 'hide':
newState.show = false;
return newState;
default :
return prevState;
}
}
const store = createStore(reducer);
export default store;
6. antdmobile+ts
import React, { Component,createRef } from 'react'
import { Button, Swiper } from 'antd-mobile'
import { SwiperRef } from 'antd-mobile/es/components/swiper'
export default class App extends Component {
myref = createRef<SwiperRef>();
colors = ['#ace0ff', '#bcffbd', '#e4fabd', '#ffcfac'];
items = this.colors.map((color, index) => (
<Swiper.Item key={index}>
<div style={{height:'200px',width:'100%',background: color}}>
{index + 1}
</div>
</Swiper.Item>
));
render() {
return (
<div>
<Swiper ref={this.myref}>{this.items}</Swiper>
<Button color="danger" onClick={()=>{
this.myref.current?.swipePrev();//原生js方法?前为真就执行?后的代码
}}>上一个</Button>
<Button color="primary" onClick={()=>{
// (this.myref.current as any).swipeNext();
(this.myref.current as SwiperRef).swipeNext();
}}>下一个</Button>
</div>
)
}
}