第一次用Vue3+ts,採用了eslint(aribnb),遇到了一些問題,又不想用常常性使用any,只能逼迫本身解決問題。javascript
本文只是記錄一些本身遇到的檢測問題html
報錯內容:vue
Cannot find module 'xxx.less' or its corresponding type declarations.
複製代碼
解決方法:java
const { proxy } = getCurrentInstance();
複製代碼
提示報錯內容:git
Property 'proxy' does not exist on type 'ComponentInternalInstance | null'.
複製代碼
解決方法:github
1.直接強制確認,由於毫無疑問,在頁面或組件中,CurrentInstance必定存在,所以可使用!強制標記存在vue-cli
但在aribnb的eslint規則下,仍然會報警告typescript
const { proxy } = getCurrentInstance()!;
複製代碼
2.使用as強轉express
import { ComponentInternalInstance } from 'vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
複製代碼
<template>
<div :ref="setDivRef" />
</template>
<script lang="ts"> import { defineComponent, ref } from 'vue'; export default defineComponent({ setup() { const divRef = ref<HTMLElement>(); const setDivRef = (el: HTMLElement) => { divRef.value = el; }; return { setDivRef, }; }, }); </script> 複製代碼
報錯內容:
Property 'resetFields' does not exist on type 'HTMLElement'
Property 'validate' does not exist on type 'HTMLElement'
複製代碼
解決方法:
使用InstanceType<typeof ElForm>
做爲範型約束
<template>
<!-- 表單 -->
<el-form :model="form" :ref="setFormRef" label-width="100px"> <!-- 註釋 --> </el-form>
</template>
<script lang="ts">
import { ElForm } from 'element-plus';
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const formRef = ref<InstanceType<typeof ElForm>>();
const setFormRef = (el: InstanceType<typeof ElForm>) => {
formRef.value = el;
};
const resetForm = () => {
formRef.value?.resetFields();
};
const confirm = () => {
formRef.value?.validate((valid) => {
if (valid) {
// do
}
});
};
return {
setFormRef,
resetForm,
confirm,
formRef,
};
},
});
</script>
複製代碼
參考:
Vue.js の Composition API における this.$refs の取得方法
報錯內容:
Property 'xxx' does not exist on type 'Readonly<{ [x: number]: string; } & { length?: number | undefined; toString?: string | undefined; toLocaleString?: string | undefined; concat?: string[] | undefined; join?: string | undefined; slice?: string[] | undefined; ... 16 more ...; flat?: unknown[] | undefined; }> | Readonly<...>'.
Property 'xxx' does not exist on type 'Readonly<{ [x: number]: string; } & { length?: number | undefined; toString?: string | undefined; toLocaleString?: string | undefined; concat?: string[] | undefined; join?: string | undefined; slice?: string[] | undefined; ... 16 more ...; flat?: unknown[] | undefined; }>'.
複製代碼
解決方法:
額外添加一個interface,名字任意,並將setup的props參數類型標記爲定義類型
<script lang="ts">
import {
computed,
defineComponent,
} from 'vue';
interface Props1 {
modelValue: boolean;
loading: boolean;
}
export default defineComponent({
props: {
modelValue: {
type: Boolean,
default: false,
},
loading: {
type: Boolean,
default: false,
},
},
setup(props: Props1, context) {
const visible = computed({
get: () => props.modelValue,
});
const loadingnow = computed({
get: () => props.loading,
});
return {
visible,
loadingnow,
};
},
});
</script>
複製代碼
解決方法:
使用vscode,並添加vetur插件>0.29.0版本,在配置中添加
vetur.experimental.templateInterpolationService: true
複製代碼
參考: 木子李的回答
(實際上?這個語法糖,除了ts,js在ES2020中也支持了,因此我以爲這個判讀機制該升級了)
例如:
const foo = bar && bar.tea && bar.tea.cup;
//簡寫爲
const foo = bar?.tea?.cup;
複製代碼
報錯內容:
Expected an assignment or function call and instead saw an expression. eslint(no-unused-expressions)
複製代碼
解決方法:
若是是使用vue-cli建立的項目,默認會引入'@typescript-eslint'
在eslint配置規則中,關閉'no-unused-expressions',開啓'@typescript-eslint/no-unused-expressions'
'no-unused-expressions': 'off',
'@typescript-eslint/no-unused-expressions': 'error',
複製代碼
參考:
Typescript optional chaining and ESLint no-unused-expressions
掛載代碼:
//main.ts
import axios from 'axios';
app.config.globalProperties.$api = axios;
複製代碼
使用代碼:
setup(){
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
proxy.$api.xxx
}
複製代碼
會發現根本沒有任何提示,而且會報錯
解決方法:
新建一個xxx.d.ts聲明文件,並在tsconfig中引入(可使用include,也可使用typeRoots等,主要看本身項目配置和路徑)。
import { AxiosInstance } from 'axios';
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$api: AxiosInstance;
}
}
複製代碼
參考: componentPublicInstance.ts#L41-L66
// api.ts
export default {
login:()=> axios.get(xxx,xxx),
xxx
}
複製代碼
這種,有n個接口,而且隨着項目變更,我目前是手動寫了一個d.ts,描述了一個interface,相似
// api.d.ts
export interface Api{
login:()=>{}
xxx
xxx
xxx
}
複製代碼
這樣,可是每新增一個接口,或者變更,我就要手動添加聲明。請問有沒有什麼辦法能把我解放出來TAT。
由於依賴了比較多的東西,我使用tsc命令單獨爲這個文件生成d.ts的時候會報錯,沒法生成。
求個答案,大佬們都是怎麼作的。