欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

Typescript類(lèi)型檢查原理之Override怎么實(shí)現(xiàn)

這篇文章將為大家詳細(xì)講解有關(guān)Typescript 類(lèi)型檢查原理之Override怎么實(shí)現(xiàn),小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

我們提供的服務(wù)有:成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、微信公眾號(hào)開(kāi)發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、黃山區(qū)ssl等。為上千多家企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢(xún)和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的黃山區(qū)網(wǎng)站制作公司

override 修飾符是干嘛的

首先,我們來(lái)看下這個(gè)修飾符的作用:被 override 標(biāo)示的方法必須得在父類(lèi)中存在,否則會(huì)報(bào)錯(cuò)。

class Animal {   getName() { return ''; } } class Dog extends Animal {   override bak() {     return 'wang';   }   override getName() {     return 'wang';   } }

上面這段代碼會(huì)報(bào)錯(cuò):This member cannot have an 'override' modifier because it is not  declared in the base class  'Animal'.就是說(shuō)重寫(xiě)的放在父類(lèi)不存在,這樣能避免父類(lèi)重構(gòu)的時(shí)候把一些子類(lèi)需要重寫(xiě)的方法給去掉。

Typescript 類(lèi)型檢查原理之Override怎么實(shí)現(xiàn)

如何實(shí)現(xiàn) override 修飾符的類(lèi)型檢查

其實(shí)所有的修飾符,包括 override、public、static 等,在 parse 成 AST 后都是作為一個(gè)屬性存在的,這個(gè) override  也是,我們通過(guò) astexplorer.net 來(lái)查看一下。

Typescript 類(lèi)型檢查原理之Override怎么實(shí)現(xiàn)

可以看到 override 屬性為 true。這樣我們就可以通過(guò)這個(gè)屬性把該 class 的所有的需要 override 的 ClassMethod  過(guò)濾出來(lái)。

然后還可以拿到 superClass 的名字,從作用域中找到對(duì)應(yīng)的聲明,然后遍歷 AST 找到它所聲明的所有 ClassMethod。

兩者對(duì)比一下,所有不在父類(lèi)中的 ClassMethod 都需要報(bào)錯(cuò)。

代碼實(shí)現(xiàn)

我們基于 babel 來(lái)做 parser 和分析,寫(xiě)一個(gè)插件來(lái)做 override 的類(lèi)型檢查。關(guān)于 babel 插件的基礎(chǔ)可以看小冊(cè)《babel  插件通關(guān)秘籍》。

開(kāi)啟語(yǔ)法 typescript 插件來(lái)解析 ts 語(yǔ)法。

const { transformFromAstSync } = require('@babel/core'); const  parser = require('@babel/parser');  const ast = parser.parse(sourceCode, {     sourceType: 'unambiguous',     plugins: ['typescript'] });  const { code } = transformFromAstSync(ast, sourceCode, {     plugins: [overrideCheckerPlugin] });

插件要處理的是 ClassDeclaration,我們先搭一個(gè)基本的結(jié)構(gòu):

const { declare } = require('@babel/helper-plugin-utils');  const overrideCheckerPlugin = declare((api, options, dirname) => {     api.assertVersion(7);      return {         pre(file) {             file.set('errors', []);         },         visitor: {             ClassDeclaration(path, state) {                 const semanticErrors = state.file.get('errors');                 //...                 state.file.set('errors', semanticErrors);             }         },         post(file) {             console.log(file.get('errors'));         }     } });

具體的檢查邏輯是拿到父類(lèi)的所有方法名,拿到當(dāng)前類(lèi)的所有 override 方法名,然后做下過(guò)濾。

我們首先要拿到父類(lèi)的 ast,通過(guò)名字從作用域中查找。

const superClass = path.node.superClass; if (superClass) {     const superClassPath = path.scope.getBinding(superClass.name).path; }

然后封裝一個(gè)方法來(lái)拿父類(lèi)方法名,通過(guò) path.traverse 來(lái)遍歷 ast,把收集到的方法名存到 state 中。

function getAllClassMethodNames(classDeclarationNodePath) {     const state = {         allSuperMethodNames: []     }     classDeclarationNodePath.traverse({         ClassMethod(path) {             state.allSuperMethodNames.push(path.get('key').toString())         }     });     return state.allSuperMethodNames; }

這樣就拿到了所有父類(lèi)方法名。

之后需要拿到當(dāng)前類(lèi)的所有方法名并過(guò)濾出 override 為 true 且不在父類(lèi)中的進(jìn)行報(bào)錯(cuò)。

const superClass = path.node.superClass; if (superClass) {     const superClassPath = path.scope.getBinding(superClass.name).path;     const allMethodNames = getAllClassMethodNames(superClassPath);      path.traverse({         ClassMethod(path) {             if (path.node.override){                 const methodName = path.get('key').toString();                 const superClassName = superClassPath.get('id').toString();                 if (!allMethodNames.includes(methodName)) {                     // 報(bào)錯(cuò)                                                     }             }         }     }); }

報(bào)錯(cuò)的部分使用 code frame 來(lái)創(chuàng)建友好的代碼打印格式,通過(guò) Error.stackTraceLimit 設(shè)置為 0 去掉調(diào)用棧信息。

const tmp = Error.stackTraceLimit; Error.stackTraceLimit = 0; let errorMessage = `this member cannot have an 'override' modifier because it is not declared in the base class '${superClassName}'`; semanticErrors.push(path.get('key').buildCodeFrameError(errorMessage, Error)); Error.stackTraceLimit = tmp;

這樣,我們就完成了 override 的類(lèi)型檢查,整體代碼如下:

const { declare } = require('@babel/helper-plugin-utils');  function getAllClassMethodNames(classDeclarationNodePath) {     const state = {         allSuperMethodNames: []     }     classDeclarationNodePath.traverse({         ClassMethod(path) {             state.allSuperMethodNames.push(path.get('key').toString())         }     });     return state.allSuperMethodNames; }  const overrideCheckerPlugin = declare((api, options, dirname) => {     api.assertVersion(7);      return {         pre(file) {             file.set('errors', []);         },         visitor: {             ClassDeclaration(path, state) {                 const semanticErrors = state.file.get('errors');                  const superClass = path.node.superClass;                 if (superClass) {                     const superClassPath = path.scope.getBinding(superClass.name).path;                     const allMethodNames = getAllClassMethodNames(superClassPath);                              path.traverse({                         ClassMethod(path) {                             if (path.node.override){                                 const methodName = path.get('key').toString();                                 const superClassName = superClassPath.get('id').toString();                                 if (!allMethodNames.includes(methodName)) {                                     const tmp = Error.stackTraceLimit;                                     Error.stackTraceLimit = 0;                                     let errorMessage = `this member cannot have an 'override' modifier because it is not declared in the base class '${superClassName}'`;                                     semanticErrors.push(path.get('key').buildCodeFrameError(errorMessage, Error));                                     Error.stackTraceLimit = tmp;                                                                     }                             }                         }                     });                 }                 state.file.set('errors', semanticErrors);             }         },         post(file) {             console.log(file.get('errors'));         }     } });  module.exports = overrideCheckerPlugin;

github 鏈接

測(cè)試效果

我們用最開(kāi)始的代碼來(lái)測(cè)試一下:

class Animal {     getName() { return ''; } } class Dog extends Animal {     override bak() {         return 'wang';     }     override getName() {         return 'wang';     } }

打印信息為:

Typescript 類(lèi)型檢查原理之Override怎么實(shí)現(xiàn)

正確的識(shí)別出了 bak 在父類(lèi)不存在的錯(cuò)誤。

至此,我們實(shí)現(xiàn)了 override 的類(lèi)型檢查!

總結(jié)

類(lèi)型檢查情況很多,所以需要一個(gè)系列文章去講,這一篇我們來(lái)實(shí)現(xiàn) override 的類(lèi)型檢查。

override 是 ts 4.3 加入的特性,帶有 override 修飾符的方法必須在父類(lèi)中有對(duì)應(yīng)的聲明,否則會(huì)報(bào)錯(cuò)。

我們通過(guò) babel 插件的方式實(shí)現(xiàn)了類(lèi)型檢查,思路是從作用域取出父類(lèi)的聲明,然后通過(guò) path.traverse  拿到所有方法名,之后再取當(dāng)前類(lèi)的所有方法名,對(duì)于沒(méi)在父類(lèi)中聲明并且?guī)в?override 修飾符的方法進(jìn)行報(bào)錯(cuò)。

關(guān)于“Typescript 類(lèi)型檢查原理之Override怎么實(shí)現(xiàn)”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

網(wǎng)站名稱(chēng):Typescript類(lèi)型檢查原理之Override怎么實(shí)現(xiàn)
標(biāo)題鏈接:http://chinadenli.net/article22/gidijc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、ChatGPT品牌網(wǎng)站設(shè)計(jì)、企業(yè)建站、響應(yīng)式網(wǎng)站、用戶(hù)體驗(yàn)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)