新聞中心
模板類型檢查概述
正如 TypeScript 在代碼中捕獲類型錯誤一樣,Angular 也會檢查應(yīng)用程序模板中的表達(dá)式和綁定,并可以報告所發(fā)現(xiàn)的任何類型錯誤。Angular 當(dāng)前有三種執(zhí)行此操作的模式,具體取決于 TypeScript 配置文件 中的 ?fullTemplateTypeCheck ?和 ?strictTemplates ?標(biāo)志的值。

創(chuàng)新互聯(lián)建站主營昆都侖網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,手機(jī)APP定制開發(fā),昆都侖h5微信平臺小程序開發(fā)搭建,昆都侖網(wǎng)站營銷推廣歡迎昆都侖等地區(qū)企業(yè)咨詢
基本模式
在最基本的類型檢查模式下,將 ?fullTemplateTypeCheck ?標(biāo)志設(shè)置為 ?false?,Angular 僅驗證模板中的頂層表達(dá)式。
如果編寫 ??,則編譯器將驗證以下內(nèi)容:
- ?
user?是該組件類的屬性 - ?
user?是具有 ?address?屬性的對象 - ?
user.address? 是具有 ?city?屬性的對象
編譯器不會驗證 ?user.address.city? 的值是否可賦值給 ?? 組件的輸入屬性 ?city?。
編譯器在此模式下也有一些主要限制:
- 重要的是,它不會檢查嵌入式視圖,比如 ?
*ngIf?,?*ngFor? 和其它 ?? 嵌入式視圖。 - 它無法弄清 ?
#refs? 的類型、管道的結(jié)果、事件綁定中 ?$event? 的類型等等。
在許多情況下,這些東西最終都以 ?any ?類型結(jié)束,這可能導(dǎo)致表達(dá)式的后續(xù)部分不受檢查。
完全模式
如果將 ?fullTemplateTypeCheck ?標(biāo)志設(shè)置為 ?true?,則 Angular 在模板中進(jìn)行類型檢查時會更加主動。特別是:
- 檢查嵌入式視圖(比如 ?
*ngIf? 或 ?*ngFor? 內(nèi)的 ?*ngFor?) - 管道具有正確的返回類型
- 對指令和管道的本地引用具有正確的類型(any 泛型參數(shù)除外,該通用參數(shù)將是 ?
any?)
以下仍然具有 ?any ?類型。
- 對 DOM 元素的本地引用。
- ?
$event? 對象 - 安全導(dǎo)航表達(dá)式
?
fullTemplateTypeCheck?標(biāo)志已經(jīng)在 Angular 13 中棄用了。它被編譯器選項中的 ?strictTemplates?家族代替了。
嚴(yán)格模式
Angular 延續(xù)了 ?fullTemplateTypeCheck ?標(biāo)志的行為,并引入了第三個“嚴(yán)格模式”。嚴(yán)格模式是完全模式的超集,可以通過將 ?strictTemplates ?標(biāo)志設(shè)置為 true 來訪問。該標(biāo)志取代 ?fullTemplateTypeCheck ?標(biāo)志。在嚴(yán)格模式下,Angular 添加了超出 8 版類型檢查器的檢查。
注意:
嚴(yán)格模式僅在使用 Ivy 時可用。
除了完全模式的行為之外,Angular 版本 9 還會:
- 驗證組件/指令綁定是否可賦值給它們的 ?
@Input()? - 驗證以上模式時,會遵守 TypeScript 的 ?
strictNullChecks?標(biāo)志 - 推斷組件/指令的正確類型,包括泛型
- 推斷配置模板上下文的類型(比如,允許對 ?
NgFor?進(jìn)行正確的類型檢查) - 在組件/指令、DOM 和動畫事件綁定中推斷 ?
$event? 的正確類型 - 根據(jù)標(biāo)簽(tag)名稱(比如,?
document.createElement? 將為該標(biāo)簽返回正確的類型),推斷出對 DOM 元素的局部引用的正確類型
*ngFor 檢查
類型檢查的三種模式對嵌入式視圖的處理方式不同??紤]以下范例。
interface User {
name: string;
address: {
city: string;
state: string;
}
}
{{config.title}}
City: {{user.address.city}}
?? 和 ?? 在 ?*ngFor? 嵌入式視圖中。在基本模式下,Angular 不會檢查它們中的任何一個。但是,在完全模式下,Angular 會檢查 ?config ?和 ?user ?是否存在,并假設(shè)為 ?any ?的類型。在嚴(yán)格模式下,Angular 知道該 ?user ?在 ?? 中是 ?User ?類型,而 ?address ?是與一個對象,它有一個 ?string ?類型的屬性 ?city?。
排除模板錯誤
使用嚴(yán)格模式,你可能會遇到在以前的兩種模式下都沒有出現(xiàn)過的模板錯誤。這些錯誤通常表示模板中的真正類型不匹配,而以前的工具并未捕獲這些錯誤。在這種情況下,該錯誤消息會使該問題在模板中的位置清晰可見。
當(dāng) Angular 庫的類型不完整或不正確,或者在以下情況下類型與預(yù)期不完全一致時,也可能存在誤報。
- 當(dāng)庫的類型錯誤或不完整時(比如,如果編寫庫的時候沒有注意 ?
strictNullChecks?,則可能缺少 ?null | undefined?) - 當(dāng)庫的輸入類型太窄并且?guī)鞗]有為 Angular 添加適當(dāng)?shù)脑獢?shù)據(jù)來解決這個問題時。這通常在禁用或使用其它通用布爾輸入作為屬性時發(fā)生,比如 ?
?。 - 在將 ?
$event.target? 用于 DOM 事件時(由于事件冒泡的可能性,DOM 類型中的 ?$event.target? 不具有你可能期望的類型)
如果發(fā)生此類誤報,則有以下幾種選擇:
- 在某些情況下,使用 ?
$any()? 類型轉(zhuǎn)換函數(shù)可以選擇不對部分表達(dá)式進(jìn)行類型檢查 - 你可以通過在應(yīng)用程序的 TypeScript 配置文件 ?
tsconfig.json? 中設(shè)置 ?strictTemplates: false? 來完全禁用嚴(yán)格檢查 - 通過將嚴(yán)格性標(biāo)志設(shè)置為 ?
false?,可以在保持其它方面的嚴(yán)格性的同時,單獨(dú)禁用某些特定的類型檢查操作 - 如果要一起使用 ?
strictTemplates?和 ?strictNullChecks?,則可以通過 ?strictNullInputTypes?來選擇性排除專門用于輸入綁定的嚴(yán)格空類型檢查
除非另行說明,下面的每個選項都會設(shè)置為 ?strictTemplates ?的值(當(dāng) ?strictTemplates ?為真時是 ?true?,其他值也一樣)。
|
嚴(yán)格標(biāo)志 |
影響 |
|---|---|
strictInputTypes | 是否檢查綁定表達(dá)式對 `@Input()` 字段的可賦值性。也會影響指令泛型類型的推斷。 |
strictInputAccessModifiers | 在把綁定表達(dá)式賦值給 `@Input()` 時,是否檢查像 `private`/`protected`/`readonly` 這樣的訪問修飾符。如果禁用,則 `@Input` 上的訪問修飾符會被忽略,只進(jìn)行類型檢查。本選項默認(rèn)為 `false`,即使當(dāng) `strictTemplates` 為 `true` 時也一樣。 |
strictNullInputTypes | 檢查 `@Input()` 綁定時是否要 `strictNullChecks`(對于每個 `strictInputTypes`)。當(dāng)使用的庫不是基于 `strictNullChecks` 構(gòu)建的時,將其關(guān)閉會很有幫助。 |
strictAttributeTypes | 是否檢查使用文本屬性進(jìn)行的 (將 (將 |
strictSafeNavigationTypes | 是否根據(jù) `user` 的類型正確推斷出安全導(dǎo)航操作的返回類型(比如 `user?.name`)。如果禁用,則 `user?.name` 的類型為 `any`。 |
strictDomLocalRefTypes | 對 DOM 元素的本地引用是否將具有正確的類型。如果禁用,對于 `` 來說 `ref` 會是 `any` 類型的。 |
strictOutputEventTypes | 對于綁定到組件/指令 `@Output()` 或動畫事件的事件綁定,`$event` 是否具有正確的類型。如果禁用,它將為 `any`。 |
strictDomEventTypes | 對于與 DOM 事件的事件綁定,`$event` 是否具有正確的類型。如果禁用,它將為 `any`。 |
strictContextGenerics | 泛型組件的類型參數(shù)是否應(yīng)該被正確推斷(包括泛型上界和下界). 如果禁用它,所有的類型參數(shù)都會被當(dāng)做 `any`。 |
strictLiteralTypes | 是否要推斷模板中聲明的對象和數(shù)組字面量的類型。如果禁用,則此類文字的類型就是 `any`。當(dāng) `fullTemplateTypeCheck` 或 `strictTemplates` 為 `true` 時,此標(biāo)志為 `true`。 |
如果使用這些標(biāo)志進(jìn)行故障排除后仍然存在問題,可以通過禁用 ?strictTemplates ?退回到完全模式。
如果這不起作用,則最后一種選擇是完全關(guān)閉 full 模式,并使用 ?fullTemplateTypeCheck: false?,因為在這種情況下,我們已經(jīng)做了一些特殊的努力來使 Angular 9 向后兼容。
你無法使用任何推薦方式解決的類型檢查錯誤可能是因為模板類型檢查器本身存在錯誤。如果遇到需要退回到基本模式的錯誤,則很可能是這樣的錯誤。如果發(fā)生這種情況,請?zhí)岢鰡栴},以便開發(fā)組解決。
輸入屬性與類型檢查
模板類型檢查器會檢查綁定表達(dá)式的類型是否與相應(yīng)指令輸入的類型兼容。比如,請考慮以下組件:
export interface User {
name: string;
}
@Component({
selector: 'user-detail',
template: '{{ user.name }}',
})
export class UserDetailComponent {
@Input() user: User;
}?AppComponent ?模板按以下方式使用此組件:
@Component({
selector: 'app-root',
template: ' ',
})
export class AppComponent {
selectedUser: User | null = null;
}這里,在檢查 ?AppComponent ?的模板期間,?[user]="selectedUser"? 綁定與 ?UserDetailComponent.user? 輸入屬性相對應(yīng)。因此,Angular 會將 ?selectedUser ?屬性賦值給 ?UserDetailComponent.user?,如果它們的類型不兼容,則將導(dǎo)致錯誤。TypeScript 會根據(jù)其類型系統(tǒng)進(jìn)行賦值檢查,并遵循在應(yīng)用程序中配置的標(biāo)志(比如 ?strictNullChecks?)。
通過向模板類型檢查器提出更具體的模板內(nèi)類型要求,可以避免一些運(yùn)行時類型錯誤。通過在指令定義中提供各種“模板守衛(wèi)”功能,可以讓自定義指令的輸入類型要求盡可能具體。
嚴(yán)格的空檢查
當(dāng)你啟用 ?strictTemplates ?和 TypeScript 標(biāo)志 ?strictNullChecks?,在某些情況下可能會發(fā)生類型檢查錯誤,這些情況很難避免。比如:
- 一個可空值,該值綁定到未啟用 ?
strictNullChecks?的庫中的指令。
對于沒有使用 ?strictNullChecks ?編譯的庫,其聲明文件將不會指示字段是否可以為 ?null?。對于庫正確處理 ?null ?的情況,這是有問題的,因為編譯器將根據(jù)聲明文件進(jìn)行空值檢查,而它省略了 ?null ?類型。這樣,編譯器會產(chǎn)生類型檢查錯誤,因為它要遵守 ?strictNullChecks?。
- 將 ?
async?管道與 Observable 一起使用會同步發(fā)出值。
?async ?管道當(dāng)前假定它預(yù)訂的 Observable 可以是異步的,這意味著可能還沒有可用的值。在這種情況下,它仍然必須返回某些內(nèi)容 —— ?null?。換句話說,?async ?管道的返回類型包括 ?null?,這在知道此 Observable 會同步發(fā)出非空值的情況下可能會導(dǎo)致錯誤。
對于上述問題,有兩種潛在的解決方法:
- 在模板中,包括非空斷言運(yùn)算符 ?
!? 用在可為空的表達(dá)式的末尾,比如
在此范例中,編譯器在可空性方面會忽略類型不兼容,就像在 TypeScript 代碼中一樣。對于 ?async ?管道,請注意,表達(dá)式需要用括號括起來,如
當(dāng)啟用 ?strictTemplates ?時,仍然可以禁用類型檢查的某些方面。將選項 ?strictNullInputTypes ?設(shè)置為 ?false ?將禁用 Angular 模板中的嚴(yán)格空檢查。此標(biāo)志會作用于應(yīng)用程序中包含的所有組件。
給庫作者的建議
作為庫作者,你可以采取多種措施為用戶提供最佳體驗。首先,啟用 ?strictNullChecks ?并在輸入的類型中包括 ?null?(如果適用),可以與消費(fèi)者溝通,看他們是否可以提供可空的值。
輸入 setter 強(qiáng)制類型轉(zhuǎn)換
有時,指令或組件的 ?@Input() ?最好更改綁定到它的值,通常使用此輸入的 getter / setter 對。比如,考慮以下自定義按鈕組件:
考慮以下指令:
@Component({
selector: 'submit-button',
template: `
`,
})
class SubmitButton {
private _disabled: boolean;
@Input()
get disabled(): boolean {
return this._disabled;
}
set disabled(value: boolean) {
this._disabled = value;
}
}在這里,組件的輸入 ?disabled ?將傳給模板中的 ??。只要將 ?boolean ?值綁定到輸入,所有這些工作都可以按預(yù)期進(jìn)行。但是,假設(shè)使用者使用模板中的這個輸入作為屬性:
這與綁定具有相同的效果:
在運(yùn)行時,輸入將設(shè)置為空字符串,這不是 ?boolean ?值。處理此問題的角組件庫通常將值“強(qiáng)制轉(zhuǎn)換”到 setter 中的正確類型中:
set disabled(value: boolean) {
this._disabled = (value === '') || value;
}最好在這里將 ?value ?的類型從 ?boolean ?更改為 ?boolean|''? 以匹配 setter 實際會接受的一組值。TypeScript 4.3 之前的版本要求 getter 和 setter 的類型相同,因此,如果 getter 要返回 ?boolean ?則 setter 會卡在較窄的類型上。
如果消費(fèi)者對模板啟用了 Angular 的最嚴(yán)格的類型檢查功能,則會產(chǎn)生一個問題:空字符串 ?''? 實際上無法賦值給 ?disabled ?字段,使用屬性格式寫會產(chǎn)生類型錯誤。
作為解決此問題的一種取巧方式,Angular 支持對 ?@Input()? 檢查比聲明的輸入字段更寬松的類型。通過向組件類添加帶有 ?ngAcceptInputType_ ?前綴的靜態(tài)屬性來啟用此功能:
class SubmitButton {
private _disabled: boolean;
@Input()
get disabled(): boolean {
return this._disabled;
}
set disabled(value: boolean) {
this._disabled = (value === '') || value;
}
static ngAcceptInputType_disabled: boolean|'';
}
從 TypeScript 4.3 開始,setter 能夠聲明為接受 ?
boolean|''? 類型,這就讓輸入屬性 setter 強(qiáng)制類型轉(zhuǎn)換字段過時了。因此,輸入屬性 setter 強(qiáng)制類型轉(zhuǎn)換字段也就棄用了。
該字段不需要值。它只要存在就會通知 Angular 的類型檢查器,?disabled ?輸入應(yīng)被視為接受與 ?boolean|''? 類型匹配的綁定。后綴應(yīng)為 ?@Input? 字段的名稱。
請注意,如果給定輸入存在 ?ngAcceptInputType_? 覆蓋,則設(shè)置器應(yīng)能夠處理任何覆蓋類型的值。
使用 $any() 禁用類型檢查
可以通過把綁定表達(dá)式包含在類型轉(zhuǎn)換偽函數(shù) ?$any()? 中來禁用類型檢查。編譯器會像在 TypeScript 中使用 ?? 或 ?as any? 進(jìn)行類型轉(zhuǎn)換一樣對待它。
在以下范例中,將 ?person ?強(qiáng)制轉(zhuǎn)換為 ?any ?類型可以壓制錯誤 ?Property address does not exist?。
@Component({
selector: 'my-component',
template: '{{$any(person).addresss.street}}'
})
class MyComponent {
person?: Person;
} 名稱欄目:創(chuàng)新互聯(lián)Angular教程:Angular模板類型檢查
鏈接URL:http://m.5511xx.com/article/cosiccs.html


咨詢
建站咨詢
