TypeScript 新語法 satisfies:用聲明還是用推導(dǎo)?這是個(gè)問題
用了 TypeScript 之后,我們就可以聲明類型,然后給 js 變量加上這個(gè)類型。
比如這樣:

就有類型提示了:

也會(huì)做類型檢查:

但也不是所有的變量都要手動(dòng)聲明類型,因?yàn)?ts 會(huì)做自動(dòng)類型推導(dǎo):

同樣是有類型提示和檢查的:


而且推導(dǎo)的時(shí)候還可以加上 as const,這樣推導(dǎo)出的是字面量類型(不過會(huì)有 readonly 的修飾):

那問題來了,什么時(shí)候手動(dòng)聲明類型,什么時(shí)候用自動(dòng)推導(dǎo)呢?
比如上面這個(gè) obj,b 屬性推導(dǎo)出的是 string,但其實(shí)也可能是一個(gè) number。

但給它賦值 number 會(huì)報(bào)錯(cuò):

這種就得手動(dòng)聲明類型了:

還有,函數(shù)的參數(shù),只有調(diào)用的時(shí)候才能知道參數(shù)具體的類型,這時(shí)候怎么自動(dòng)推導(dǎo)?
沒辦法推導(dǎo)。
所以也得手動(dòng)聲明類型:

總之,ts 代碼包括自動(dòng)推導(dǎo)出的類型、手動(dòng)聲明的類型兩種。
自動(dòng)類型推導(dǎo)省去了很多寫類型的麻煩,但很多情況下還是要手動(dòng)聲明類型的。
但手動(dòng)聲明的類型是有局限性的,比如這樣的類型:

key:string 那部分是索引簽名,也就是任意的 key 為 string,value 為任意類型的索引都可以加。
它是可以檢查出類型錯(cuò)誤,也支持?jǐn)U展任意索引。

但它只會(huì)提示聲明的索引,動(dòng)態(tài)添加的那些是不會(huì)提示的:

這樣其實(shí)有的時(shí)候并不方便。
而如果自動(dòng)推導(dǎo)呢?

這樣就可以提示所有的索引了。
但是呢其中 b 的類型又不對(duì),還是需要聲明類型來約束。
是不是就很頭疼?
用聲明的方式少了具體賦值的變量類型的信息,用自動(dòng)推導(dǎo)的方式又不能保證類型是對(duì)的。
有沒有兩全其美的辦法呢?
4.9 之前還真沒有。
不過 4.9 加入了一個(gè) satisfies 的新語法。
這樣用:

不需要給變量聲明這個(gè)類型了,用自動(dòng)推導(dǎo)出來的類型,這樣提示就是根據(jù)具體的值來的。
而且,還有了聲明的方式的類型檢查。

是不是兩全其美!
這就是為什么 ts 要增加 satisfies 這個(gè)語法。
它的作用就是讓你用自動(dòng)推導(dǎo)出的類型,而不是聲明的類型,增加靈活性,同時(shí)還可以對(duì)這個(gè)推導(dǎo)出的類型做類型檢查,保證安全。
但是,satisfies 的方式也有它的問題,比如這里用了推導(dǎo)出的類型:

那就不能動(dòng)態(tài)擴(kuò)展索引了:

而如果是聲明的那種索引簽名,是支持?jǐn)U展的:

所以,具體什么時(shí)候用聲明的類型,什么時(shí)候用推導(dǎo)出的類型 + satisfies,還是要看情況的。
這個(gè)新語法還是很有用的,估計(jì)以后在代碼里會(huì)經(jīng)??吹?。
不過現(xiàn)在還沒咋見,因?yàn)樗€是在 beta 的版本。
需要下載 ts 指定 beta 才行:
npm install typescript@beta
這里的 @beta 是指定標(biāo)簽的意思。
我猜大家都用過 xxx@latest 的方式下載過 npm 包。
這個(gè) latest 也同樣是標(biāo)簽。
你可以通過 npm dist-tag ls 的方式看到 npm 包的所有 tag:

所以說 npm install typescript 是下載不了 beta 版本的包的,它下載的是 latest 的 tag 對(duì)應(yīng)的版本。只有手動(dòng)指定 typescript@beta 才可以。
說點(diǎn)題外話,這個(gè) tag 是怎么打上的呢?
發(fā)包的時(shí)候會(huì)用 npm publish,這種會(huì)自動(dòng)打上 latest 的 tag。
也可以手動(dòng) npm publish --tags beta,這樣打的就是 beta 的 tag了。
除了發(fā)包的時(shí)候可以指定 tag,平時(shí)也可以通過 npm dist-tag 命令來給某個(gè)版本的包打上 tag:

估計(jì)用不了多久,這個(gè)特性就會(huì)加到正式包里了。
總結(jié)
TypeScript 中變量的類型有兩種,一種是手動(dòng)聲明的,一種是自動(dòng)推導(dǎo)的。
大多數(shù)情況下,不用手動(dòng)聲明類型,用自動(dòng)推導(dǎo)的就行,比較方便。
但像函數(shù)參數(shù)、需要約束的變量類型等情況下即得手動(dòng)聲明了。
有的時(shí)候還是自動(dòng)推導(dǎo)出的類型更合適一些,但是還需要通過聲明的方式對(duì)其中的類型做約束。
不能兩全其美。
所以 ts 加入了 satisfies 的語法,這樣就可以用自動(dòng)推導(dǎo)出的類型了,它也可以加上類型的約束。
算是融合了自動(dòng)推導(dǎo)的類型和手動(dòng)聲明的類型的優(yōu)點(diǎn)。
現(xiàn)在這個(gè)語法還在 4.9-beta 的包里,需要 npm install 的時(shí)候手動(dòng)指定 dist-tag。
估計(jì)等它到正式版之后,你再寫 ts 代碼會(huì)有新的糾結(jié)了:
我是用手動(dòng)聲明的類型,還是自動(dòng)推導(dǎo)的類型 + satiesfies 呢?這是個(gè)問題。
