推荐的
-
官网要全部看一遍 里面有些面试题标准的答案
- interface 和 type 有什么区别
- ts中的泛型是什么
- ts中 any unkown never void 含义区别
- jsx 类型的泛型
- 等等...
-
- react + ts 的使用 很详细
-
- 大佬写的 基本看完感觉日常没有任何问题了
- 类型体操自己写不出来也有思路或者能在开源的找
- 例如项目里面 什么驼峰转下划线之类的
-
- ts类型体操的刷题的。大概刷刷就行 加强巩固
大概这四个我看了后研究了下 antd 和 Procomponents 的ts类型,目前感觉业务的话这个水平就差不多够用了。
后续话可以自己看看 typescript 实现原理啊, 自己怎么实现一个typescript, tsconfig每个配置的含义啊等等之类的
一些文档
- TypeScript 官方文档
- TypeScript 中文汉化部分文档
- 深刻理解 TypeScript 英语文档
- 深刻理解 TypeScript 中文文档
- React+TypeScript
- TypeScript 官网文档 Advanced Types
- TypeScript 参数简化实战(进阶知识点 conditional types,中高级必会)
- 有趣的 TypeScript 代码
- 用 ts 实现各种自定义 hook
- react-redux 与 TypeScript
- Type-challenges
- TypeScript 类型体操通关秘籍
其他文档
- React + Typescript 工程化治理实践
- Writing Type-Safe Polymorphic React Components (Without Crashing TypeScript)
- 10++ TypeScript Pro tips/patterns with (or without) React
- TS 一些工具泛型的使用及其实现
- 巧用 TypeScript(五)-- infer
- Conditional Types in TypeScript
- Vue Ref 拆包源代码
- Vue3 跟着尤雨溪学 TypeScript 之 Ref 类型从零实现
ts 类型体操开源的npm包
不会写的可以在里面找找看看有没有相似的,也可以参考参考他们怎么写的。
vue组件如何添加泛型
setup-generic
// child.vue
<script setup lang="ts">
import HelloWorld from './HelloWorld.vue';
interface DataType {
name: 'zs' | 'l4';
age: number;
}
type IColumnsType = {
dataIndex: keyof DataType;
render?: (text: string, record: DataType) => any;
[props: string]: any;
}[];
const data: IColumnsType = [
{
dataIndex: 'age',
render(_text, record) {
return record.age;
},
},
{
dataIndex: 'name',
visible: false,
},
];
const params: { kw: '1' | '2' } = {
kw: '1',
};
</script>
<template>
<div>
<HelloWorld :data="data" :params="params" v-slot="{ data, params }">
{{ data[0].dataIndex == 'age' ? 1 : 2 }}
{{ params?.kw == '1' }}
</HelloWorld>
</div>
</template>
<style></style>
// HelloWorld.vue
<script lang="ts" setup generic="Record extends any[], Params extends any">
defineProps<{
data: Record;
params?: Params;
}>();
</script>
<template>
<div>
<table>
<!-- Todo: -->
</table>
<slot :data="data" :params="params" />
</div>
</template>
tsx
import { defineComponent, type PropType, type SlotsType } from 'vue'
import type { JSX } from 'vue/jsx-runtime'
type Color = 'red' | 'blue' | 'green'
type IProps<T extends Color> = T extends 'red'
? {
color: T
name?: string
}
: {
name?: string
}
export const Demo: <T extends Color>(props: IProps<T>) => JSX.Element = defineComponent({
name: 'MyDemo',
props: {
color: String as PropType<Color>,
name: String
},
slots: Object as SlotsType<{
default: (color: Color) => any
}>,
setup: (props, ctx) => {
return () => (
<>
{props.name}
{props.color}
{ctx.slots.default?.(props.color!)}
</>
)
}
}) as any
const a = <Demo />
const b = <Demo<'red'> color="red" v-slots={{ color: 'red' }} />
React+TypeScript 风格的代码
高阶组件的类型
-
详细地址参考
-
www.yuque.com/eternallycy… 《compose的使用时的类型问题》
-
class类型ref=>public readonly MyRef = React.createRef<InstanceType<typeof CustomComponent>>(); -
hooks类型的ref=>const MyRef = React.useRef<React.ElementRef<typeof CustomComponent>>(null!)- 直接用
CustomComponent组件导出的ref类型也行React.useRef<xxx>(null!)
- 直接用
-
多层高阶组件使用 compose 在最外层来定义类型
import type { PermessionProps, permissionParams } from './permission';
import { withRoutePage } from './withRoutePage';
import React, { useImperativeHandle } from 'react';
import compose from './compose';
import { withRouter } from './withRouter';
import { connect } from '@umijs/max';
import Permession from './permission';
export interface extraProps<Values = any> {
myExtraProps?: Values;
}
export interface IndexPageProps<Values = any> extends PermessionProps<Values>, permissionParams<Values>, extraProps<Values> {}
export type IndexPageHandel<Values = any> = {
setVisible: React.Dispatch<React.SetStateAction<boolean>>;
myExtraProps?: extraProps<Values>['myExtraProps'];
};
const IndexPage: React.ForwardRefRenderFunction<IndexPageHandel, IndexPageProps> = (props, ref) => {
const nnnnnnnnn = props.nnnnnnnnn;
const id = props.match?.params?.id;
const { myExtraProps } = props;
const [visible, setVisible] = React.useState<boolean>(false);
useImperativeHandle(ref, () => ({
setVisible,
myExtraProps,
}));
return <div>IndexPage</div>;
};
export default compose<typeof IndexPage>(
withRoutePage,
withRouter,
connect(
({ global, login }: any) => ({
accessCollection: login?.accessCollection || [],
}),
null,
null,
{
forwardRef: true,
pure: undefined,
},
),
Permession,
)(IndexPage, { myExtraProps: { age: 2 } });
antd风格的代码封装demo
- 组件jsx类型泛型 + xxx.Item 风格 + context + Ref
- 详细demo代码见
- antd Form内的 Form.Item绑表单的是用 context 实现的, 但日常业务组件感觉用不上。
- 一般这种封装就基本够用了
- 因为有些功能 例如流程什么 可能要封装二三十个组件 这样就比较好
- 点一下就出来了
ProcessPage.hooksProcessPage.utils... - 泛型看情况吧 一般表单最好都加下 比如编辑表格等, 其他一些业务组件一般用不上吧。
- 可以参考参考我的
- github.com/eternallycy…
- 点一下就出来了
import { useFetchProps } from '@ims-view/hooks';
import { Button, Spin } from 'antd';
import { CommonDemo, ICommonDemoHandle } from 'ims-view-pc';
import React, { useState } from 'react';
interface IRecord {
username: string;
useId: number;
}
interface IApi {
code: number;
msg: string;
success: boolean;
data: IRecord;
}
const Demo = () => {
const [number, setNumber] = useState<number>(0);
const CommonDemoRef = React.useRef<ICommonDemoHandle<IRecord>>(null!);
const params: useFetchProps<IRecord> = {
fetchConfig: {
apiUrl: '/fetchUserInfo',
method: 'post',
dataPath: 'data',
depts: [number],
},
request: async (config) => {
const data = new Promise((resolve, reject) => {
fetch(config?.url, config as any)
.then((data) => data.json())
.then((data) => resolve(data))
.catch((error) => reject(error));
});
return (await data) as IApi;
},
// dataHandler: (data) => data?.data,
};
const handleFetch = () => {
setNumber(number + 1);
};
return (
<>
<CommonDemo<IRecord> ref={CommonDemoRef} {...params}>
<Spin spinning={CommonDemoRef?.current?.loading || false}>
<Button onClick={handleFetch}>发起请求</Button>
<pre>{JSON.stringify(CommonDemoRef?.current?.data)}</pre>
</Spin>
</CommonDemo>
<CommonDemo.Item />
</>
);
};
export default Demo;
最后
想问问 vue 除了官网有没有什么高级的 ts + vue 文档, 类似这种的 React+TypeScript
感觉写泛型比较困难,ts类型支持的不好。
大家还有没有什么比较好的文章啊 可以分享分享 ~