W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
正如 TypeScript 在代碼中捕獲類型錯(cuò)誤一樣,Angular 也會檢查應(yīng)用程序模板中的表達(dá)式和綁定,并可以報(bào)告所發(fā)現(xiàn)的任何類型錯(cuò)誤。Angular 當(dāng)前有三種執(zhí)行此操作的模式,具體取決于 TypeScript 配置文件 中的 ?fullTemplateTypeCheck
?和 ?strictTemplates
?標(biāo)志的值。
在最基本的類型檢查模式下,將 ?fullTemplateTypeCheck
?標(biāo)志設(shè)置為 ?false
?,Angular 僅驗(yàn)證模板中的頂層表達(dá)式。
如果編寫 ?<map [city]="user.address.city">
?,則編譯器將驗(yàn)證以下內(nèi)容:
user
?是該組件類的屬性user
?是具有 ?address
?屬性的對象user.address
? 是具有 ?city
?屬性的對象編譯器不會驗(yàn)證 ?user.address.city
? 的值是否可賦值給 ?<map>
? 組件的輸入屬性 ?city
?。
編譯器在此模式下也有一些主要限制:
*ngIf
?,?*ngFor
? 和其它 ?<ng-template>
? 嵌入式視圖。#refs
? 的類型、管道的結(jié)果、事件綁定中 ?$event
? 的類型等等。在許多情況下,這些東西最終都以 ?any
?類型結(jié)束,這可能導(dǎo)致表達(dá)式的后續(xù)部分不受檢查。
如果將 ?fullTemplateTypeCheck
?標(biāo)志設(shè)置為 ?true
?,則 Angular 在模板中進(jìn)行類型檢查時(shí)會更加主動(dòng)。特別是:
*ngIf
? 或 ?*ngFor
? 內(nèi)的 ?*ngFor
?)any
?)以下仍然具有 ?any
?類型。
$event
? 對象?
fullTemplateTypeCheck
?標(biāo)志已經(jīng)在 Angular 13 中棄用了。它被編譯器選項(xiàng)中的 ?strictTemplates
?家族代替了。
Angular 延續(xù)了 ?fullTemplateTypeCheck
?標(biāo)志的行為,并引入了第三個(gè)“嚴(yán)格模式”。嚴(yán)格模式是完全模式的超集,可以通過將 ?strictTemplates
?標(biāo)志設(shè)置為 true 來訪問。該標(biāo)志取代 ?fullTemplateTypeCheck
?標(biāo)志。在嚴(yán)格模式下,Angular 添加了超出 8 版類型檢查器的檢查。
注意:
嚴(yán)格模式僅在使用 Ivy 時(shí)可用。
除了完全模式的行為之外,Angular 版本 9 還會:
@Input()
?strictNullChecks
?標(biāo)志NgFor
?進(jìn)行正確的類型檢查)$event
? 的正確類型document.createElement
? 將為該標(biāo)簽返回正確的類型),推斷出對 DOM 元素的局部引用的正確類型類型檢查的三種模式對嵌入式視圖的處理方式不同。考慮以下范例。
interface User {
name: string;
address: {
city: string;
state: string;
}
}
<div *ngFor="let user of users">
<h2>{{config.title}}</h2>
<span>City: {{user.address.city}}</span>
</div>
?<h2>
? 和 ?<span>
? 在 ?*ngFor
? 嵌入式視圖中。在基本模式下,Angular 不會檢查它們中的任何一個(gè)。但是,在完全模式下,Angular 會檢查 ?config
?和 ?user
?是否存在,并假設(shè)為 ?any
?的類型。在嚴(yán)格模式下,Angular 知道該 ?user
?在 ?<span>
? 中是 ?User
?類型,而 ?address
?是與一個(gè)對象,它有一個(gè) ?string
?類型的屬性 ?city
?。
使用嚴(yán)格模式,你可能會遇到在以前的兩種模式下都沒有出現(xiàn)過的模板錯(cuò)誤。這些錯(cuò)誤通常表示模板中的真正類型不匹配,而以前的工具并未捕獲這些錯(cuò)誤。在這種情況下,該錯(cuò)誤消息會使該問題在模板中的位置清晰可見。
當(dāng) Angular 庫的類型不完整或不正確,或者在以下情況下類型與預(yù)期不完全一致時(shí),也可能存在誤報(bào)。
strictNullChecks
?,則可能缺少 ?null | undefined
?)<input disabled>
?。$event.target
? 用于 DOM 事件時(shí)(由于事件冒泡的可能性,DOM 類型中的 ?$event.target
? 不具有你可能期望的類型)如果發(fā)生此類誤報(bào),則有以下幾種選擇:
$any()
? 類型轉(zhuǎn)換函數(shù)可以選擇不對部分表達(dá)式進(jìn)行類型檢查tsconfig.json
? 中設(shè)置 ?strictTemplates: false
? 來完全禁用嚴(yán)格檢查false
?,可以在保持其它方面的嚴(yán)格性的同時(shí),單獨(dú)禁用某些特定的類型檢查操作strictTemplates
?和 ?strictNullChecks
?,則可以通過 ?strictNullInputTypes
?來選擇性排除專門用于輸入綁定的嚴(yán)格空類型檢查除非另行說明,下面的每個(gè)選項(xiàng)都會設(shè)置為 ?strictTemplates
?的值(當(dāng) ?strictTemplates
?為真時(shí)是 ?true
?,其他值也一樣)。
嚴(yán)格標(biāo)志 |
影響 |
---|---|
strictInputTypes
|
是否檢查綁定表達(dá)式對 `@Input()` 字段的可賦值性。也會影響指令泛型類型的推斷。 |
strictInputAccessModifiers
|
在把綁定表達(dá)式賦值給 `@Input()` 時(shí),是否檢查像 `private`/`protected`/`readonly` 這樣的訪問修飾符。如果禁用,則 `@Input` 上的訪問修飾符會被忽略,只進(jìn)行類型檢查。本選項(xiàng)默認(rèn)為 `false`,即使當(dāng) `strictTemplates` 為 `true` 時(shí)也一樣。 |
strictNullInputTypes
|
檢查 `@Input()` 綁定時(shí)是否要 `strictNullChecks`(對于每個(gè) `strictInputTypes`)。當(dāng)使用的庫不是基于 `strictNullChecks` 構(gòu)建的時(shí),將其關(guān)閉會很有幫助。 |
strictAttributeTypes
|
是否檢查使用文本屬性進(jìn)行的 (將 disabled 屬性設(shè)置為字符串 'true' )
disabled 屬性設(shè)置為布爾值 true )。 |
strictSafeNavigationTypes
|
是否根據(jù) `user` 的類型正確推斷出安全導(dǎo)航操作的返回類型(比如 `user?.name`)。如果禁用,則 `user?.name` 的類型為 `any`。 |
strictDomLocalRefTypes
|
對 DOM 元素的本地引用是否將具有正確的類型。如果禁用,對于 `` 來說 `ref` 會是 `any` 類型的。 |
strictOutputEventTypes
|
對于綁定到組件/指令 `@Output()` 或動(dòng)畫事件的事件綁定,`$event` 是否具有正確的類型。如果禁用,它將為 `any`。 |
strictDomEventTypes
|
對于與 DOM 事件的事件綁定,`$event` 是否具有正確的類型。如果禁用,它將為 `any`。 |
strictContextGenerics
|
泛型組件的類型參數(shù)是否應(yīng)該被正確推斷(包括泛型上界和下界). 如果禁用它,所有的類型參數(shù)都會被當(dāng)做 `any`。 |
strictLiteralTypes
|
是否要推斷模板中聲明的對象和數(shù)組字面量的類型。如果禁用,則此類文字的類型就是 `any`。當(dāng) `fullTemplateTypeCheck` 或 `strictTemplates` 為 `true` 時(shí),此標(biāo)志為 `true`。 |
如果使用這些標(biāo)志進(jìn)行故障排除后仍然存在問題,可以通過禁用 ?strictTemplates
?退回到完全模式。
如果這不起作用,則最后一種選擇是完全關(guān)閉 full 模式,并使用 ?fullTemplateTypeCheck: false
?,因?yàn)樵谶@種情況下,我們已經(jīng)做了一些特殊的努力來使 Angular 9 向后兼容。
你無法使用任何推薦方式解決的類型檢查錯(cuò)誤可能是因?yàn)槟0孱愋蜋z查器本身存在錯(cuò)誤。如果遇到需要退回到基本模式的錯(cuò)誤,則很可能是這樣的錯(cuò)誤。如果發(fā)生這種情況,請提出問題,以便開發(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: '<user-detail [user]="selectedUser"></user-detail>',
})
export class AppComponent {
selectedUser: User | null = null;
}
這里,在檢查 ?AppComponent
?的模板期間,?[user]="selectedUser"
? 綁定與 ?UserDetailComponent.user
? 輸入屬性相對應(yīng)。因此,Angular 會將 ?selectedUser
?屬性賦值給 ?UserDetailComponent.user
?,如果它們的類型不兼容,則將導(dǎo)致錯(cuò)誤。TypeScript 會根據(jù)其類型系統(tǒng)進(jìn)行賦值檢查,并遵循在應(yīng)用程序中配置的標(biāo)志(比如 ?strictNullChecks
?)。
通過向模板類型檢查器提出更具體的模板內(nèi)類型要求,可以避免一些運(yùn)行時(shí)類型錯(cuò)誤。通過在指令定義中提供各種“模板守衛(wèi)”功能,可以讓自定義指令的輸入類型要求盡可能具體。
當(dāng)你啟用 ?strictTemplates
?和 TypeScript 標(biāo)志 ?strictNullChecks
?,在某些情況下可能會發(fā)生類型檢查錯(cuò)誤,這些情況很難避免。比如:
strictNullChecks
?的庫中的指令。對于沒有使用 ?strictNullChecks
?編譯的庫,其聲明文件將不會指示字段是否可以為 ?null
?。對于庫正確處理 ?null
?的情況,這是有問題的,因?yàn)榫幾g器將根據(jù)聲明文件進(jìn)行空值檢查,而它省略了 ?null
?類型。這樣,編譯器會產(chǎn)生類型檢查錯(cuò)誤,因?yàn)樗袷?nbsp;?strictNullChecks
?。
async
?管道與 Observable 一起使用會同步發(fā)出值。?async
?管道當(dāng)前假定它預(yù)訂的 Observable 可以是異步的,這意味著可能還沒有可用的值。在這種情況下,它仍然必須返回某些內(nèi)容 —— ?null
?。換句話說,?async
?管道的返回類型包括 ?null
?,這在知道此 Observable 會同步發(fā)出非空值的情況下可能會導(dǎo)致錯(cuò)誤。
對于上述問題,有兩種潛在的解決方法:
!
? 用在可為空的表達(dá)式的末尾,比如<user-detail [user]="user!"></user-detail>
在此范例中,編譯器在可空性方面會忽略類型不兼容,就像在 TypeScript 代碼中一樣。對于 ?async
?管道,請注意,表達(dá)式需要用括號括起來,如
<user-detail [user]="(user$ | async)!"></user-detail>
當(dāng)啟用 ?strictTemplates
?時(shí),仍然可以禁用類型檢查的某些方面。將選項(xiàng) ?strictNullInputTypes
?設(shè)置為 ?false
?將禁用 Angular 模板中的嚴(yán)格空檢查。此標(biāo)志會作用于應(yīng)用程序中包含的所有組件。
作為庫作者,你可以采取多種措施為用戶提供最佳體驗(yàn)。首先,啟用 ?strictNullChecks
?并在輸入的類型中包括 ?null
?(如果適用),可以與消費(fèi)者溝通,看他們是否可以提供可空的值。
有時(shí),指令或組件的 ?@Input()
?最好更改綁定到它的值,通常使用此輸入的 getter / setter 對。比如,考慮以下自定義按鈕組件:
考慮以下指令:
@Component({
selector: 'submit-button',
template: `
<div class="wrapper">
<button [disabled]="disabled">Submit</button>
</div>
`,
})
class SubmitButton {
private _disabled: boolean;
@Input()
get disabled(): boolean {
return this._disabled;
}
set disabled(value: boolean) {
this._disabled = value;
}
}
在這里,組件的輸入 ?disabled
?將傳給模板中的 ?<button>
?。只要將 ?boolean
?值綁定到輸入,所有這些工作都可以按預(yù)期進(jìn)行。但是,假設(shè)使用者使用模板中的這個(gè)輸入作為屬性:
<submit-button disabled></submit-button>
這與綁定具有相同的效果:
<submit-button [disabled]="''"></submit-button>
在運(yùn)行時(shí),輸入將設(shè)置為空字符串,這不是 ?boolean
?值。處理此問題的角組件庫通常將值“強(qiáng)制轉(zhuǎn)換”到 setter 中的正確類型中:
set disabled(value: boolean) {
this._disabled = (value === '') || value;
}
最好在這里將 ?value
?的類型從 ?boolean
?更改為 ?boolean|''
? 以匹配 setter 實(shí)際會接受的一組值。TypeScript 4.3 之前的版本要求 getter 和 setter 的類型相同,因此,如果 getter 要返回 ?boolean
?則 setter 會卡在較窄的類型上。
如果消費(fèi)者對模板啟用了 Angular 的最嚴(yán)格的類型檢查功能,則會產(chǎn)生一個(gè)問題:空字符串 ?''
? 實(shí)際上無法賦值給 ?disabled
?字段,使用屬性格式寫會產(chǎn)生類型錯(cuò)誤。
作為解決此問題的一種取巧方式,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)換字段過時(shí)了。因此,輸入屬性 setter 強(qiáng)制類型轉(zhuǎn)換字段也就棄用了。
該字段不需要值。它只要存在就會通知 Angular 的類型檢查器,?disabled
?輸入應(yīng)被視為接受與 ?boolean|''
? 類型匹配的綁定。后綴應(yīng)為 ?@Input
? 字段的名稱。
請注意,如果給定輸入存在 ?ngAcceptInputType_
? 覆蓋,則設(shè)置器應(yīng)能夠處理任何覆蓋類型的值。
可以通過把綁定表達(dá)式包含在類型轉(zhuǎn)換偽函數(shù) ?$any()
? 中來禁用類型檢查。編譯器會像在 TypeScript 中使用 ?<any>
? 或 ?as any
? 進(jìn)行類型轉(zhuǎn)換一樣對待它。
在以下范例中,將 ?person
?強(qiáng)制轉(zhuǎn)換為 ?any
?類型可以壓制錯(cuò)誤 ?Property address does not exist
?。
@Component({
selector: 'my-component',
template: '{{$any(person).addresss.street}}'
})
class MyComponent {
person?: Person;
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: