写在前面
作为一个写php和go的后端程序员,虽然也写过js、微信小程序、uniapp,但是对于ts还是比较陌生的,曾经就有一个同事,嘲讽我写不来ts,最终还是被他言中了。甚至有同事说 “周围写ts的,没有一个不骂的
”
接触ts
最近公司的项目使用vue-element-plus-admin,ts技术栈,前面的简单功能,写写表格啥的,复制一下demo和同事的代码,其实还好,有个功能要用Echart搞拆线图。本来想着这个功能也不难,以前又不是没写过,对着官网一顿ctrl c ctrl v, 然后 npm run dev
运行得好好的,图表显示完全正常。最后想git commit死活过不了npm run ts:check,报错像小作文一样长,一个文件,90多个error,给我整懵了。。。
src/views/Monitor/Realtime.vue:47:78 - error TS18046: 'value' is of type'unknown'.
47
src/views/Monitor/Realtime.vue:51:31 - error TS2339: Property 'energy' does not exist on type'{}'.
51
src/views/Monitor/Realtime.vue:54:78 - error TS18046: 'value' is of type'unknown'.
54
src/views/Monitor/Realtime.vue:58:24 - error TS18046: 'value' is of type'unknown'.
58
src/views/Monitor/Realtime.vue:65:7 - error TS6133: 'getLatestDataList' is declared but its value is never read.
65
src/views/Monitor/Realtime.vue:18:11 - error TS2322: Type '{ [x: string]: unknown; dataset?: { mainType?: "dataset" | undefined; seriesLayoutBy?: SeriesLayoutBy | undefined; sourceHeader?: OptionSourceHeader | undefined; ... 8 more ...; dimensions?: (string | ... 1 more ... | undefined)[] | undefined; } | { ...; }[] | undefined; ... 41 more ...; colorLayer?: (string | ... 3...' is not assignable to type'EChartsOption'.
18
最痛苦的是,npm run ts:check一次要好久,简直浪费时间。
与AI的失败尝试
看到这一堆报错,咱立马将它复制到ds里面,然后ds就一顿输出给了答案,其中像error TS6133这样的我自己都能解决,对于error TS18046这样的ds解决起来也很简单,主要是error TS2322,不管是ds还是gpt,都不行,只会在错误的路上越来越远。。。
ds和gpt给的错误答案,如下:
// 尝试1
const option = {} as EChartsOption;
// 尝试2
const option = ref<EChartsOption>({});
// 尝试3
const option = reactive<EChartsOption>({});
// 尝试4
option.value = {
...option.value,
legend: {
data: res.data.legend
},
xAxis: [
{
type: 'category',
boundaryGap: false,
data: res.data.category
}
],
series: res.data.series.map((item: any) => ({
name: item.title,
type: 'line',
data: item.data
})) as SeriesOption[]
}
// 尝试5
option.value = Object.assign({}, option.value, {
legend: {
data: res.data.legend,
},
xAxis: [
{
type: "category",
boundaryGap: false,
data: res.data.category,
},
],
series: res.data.series.map((item: any) => ({
name: item.title,
type: "line",
data: item.data,
})) as SeriesOption[],
});
});
// 尝试6
const seriesData: SeriesOption[] = res.data.series.map((item: any) => ({
name: item.title,
type: "line",
data: item.data
}));
// 尝试7
option.value = {
...option.value,
series: seriesData
};
// 尝试8
function isEChartsOption(obj: any): obj is EChartsOption {
return true; // 这里应该写实际判断逻辑
}
查源码
各种调试都不行之后,就开始看源码,通过对比,发现的一点规律,用官方demo, 就可以通过npm run ts:check检查,但是只要想动态赋值,就会报错。但不可能不用后端接口数据。
问同事
查了源码也不行,只剩下最后一个办法,就是问前端同事,结果他看了一眼,轻描淡写地说: “用any吧。”
const option = ref<any>({
backgroundColor: '#ffffff',
title: {
text: ''
},
tooltip: {
trigger: 'axis'
},
legend: {
data: []
},
grid: {
left: '3%',
right: '3%',
bottom: '6%',
containLabel: false
},
xAxis: [
{
type: 'category',
boundaryGap: false,
data: []
}
],
yAxis: [
{
type: 'value',
name: '(数量)',
nameLocation: 'end'
}
],
series: [] as SeriesOption[]
})
简直不可思议,就如此简单,困扰我几天的问题一下子解决了。any就像ts的"免检通行证",让ts:check直接过了。
后续
为此我特意查了一下any, 结果如下
类型安全的"逃生舱"
在ts的世界里,any
类型就像一个特殊的逃生舱门。当你在严格的类型检查中感到窒息时,它为你提供了一条"生路"。这个看似简单的类型,实际上是TypeScript类型系统中最为复杂和争议的存在。
any
的起源可以追溯到TypeScript最早期的设计阶段。当时团队面临一个关键决策:如何让JavaScript开发者平滑过渡到TypeScript?答案是any
——它允许开发者逐步采用类型检查,而不是全有或全无的选择。这个设计决策虽然看似简单,却极大地降低了TypeScript的采用门槛,成为它成功的关键因素之一。
any的典型使用场景
在实际开发中,any
有几个合理的应用场景:
- 渐进式迁移:将JavaScript项目迁移到TypeScript时,
any
可以作为临时解决方案 - 处理动态内容:如第三方API响应、用户输入等无法预知结构的数据
- 快速原型开发:在验证概念阶段,避免被类型系统拖慢速度
- 与无类型库交互:当使用纯JavaScript编写的库时
以ECharts为例,这个强大的图表库在TypeScript中使用时经常会遇到any
的身影。考虑以下场景:
typescript
复制
const chart = echarts.init(document.getElementById('chart'));
const option: any = {
// 复杂的配置项
series: [{
type: 'pie',
data: [
{ value: 1048, name: 'Search Engine' },
{ value: 735, name: 'Direct' }
]
}]
};
chart.setOption(option);
在这个例子中,ECharts的配置对象极为复杂且嵌套深,完整定义其类型可能得不偿失。此时使用any
可以快速实现功能,但同时也埋下了隐患。
真相:EChartsOption 的类型设计问题
深入查了一下,发现 ECharts 的 EChartsOption
类型定义得非常严格,但 ECharts 运行时却非常宽松。
-
- ECharts 的
option
允许很多动态字段,但EChartsOption
没有完全涵盖这些可能性。
- ECharts 的
-
- TS 类型定义基于文档,而 ECharts 运行时可以接受更多参数。
-
- 部分字段使用了
unknown
类型,导致 TS 无法自动推导兼容性。
- 部分字段使用了
换句话说,ECharts 本身能正常跑,但 TypeScript 认为它“不够安全” 。这就是 npm run dev
没问题,npm run ts:check
却报错的原因。
综上
大家都说any大法好,能用就用,千万不要自己卷自己。
– end –