所以,型別定義:
// type definitions
class GenericDto {
public ids: string[] = [];
public dateFrom: string | null = null;
public dateTo: string | null = null;
}
class FleetInformationDto extends GenericDto { }
class VehicleInformationDto extends GenericDto { }
enum ReportQueueAction {
GENERATE
}
enum ReportQueueType {
VEHICLE_INFORMATION,
FLEET_INFORMATION
}
type ReportQueue = {
action: ReportQueueAction;
type: ReportQueueType.FLEET_INFORMATION;
dto: FleetInformationDto
} | {
action: ReportQueueAction,
type: ReportQueueType.VEHICLE_INFORMATION,
dto: VehicleInformationDto;
}
和實施:
// implementation
const dto: FleetInformationDto = {
ids: ["1", "2"],
dateFrom: '2021-01-01',
dateTo: '2021-02-01'
}
const queueData: ReportQueue = {
action: ReportQueueAction.GENERATE,
type: ReportQueueType.FLEET_INFORMATION,
dto: dto
}
// ^ works as expected
但是如果我們添加“VehicleInformationDto”到型別 FLEET_INFORMATION 它不會拋出錯誤
const dto2: VehicleInformationDto = {
ids: ["1", "2"],
dateFrom: '2021-01-01',
dateTo: '2021-02-01'
}
const queueData2: ReportQueue = {
action: ReportQueueAction.GENERATE,
type: ReportQueueType.FLEET_INFORMATION,
dto: dto2 // <-- no error thrown here
}
好吧,這里有什么問題?我錯過了什么嗎?
問題:當打字稿期望它是時,為什么我能夠分配VehicleInformationDto到dtoinside ?queueData2FleetInformationDto
編輯:好的,是的,這是因為它們共享相同的屬性,那么,我該如何添加檢查?
操場
uj5u.com熱心網友回復:
打字稿是結構型別的,而不是名義型別的。這意味著就 Typescript 而言,它們是相同的型別:
class FleetInformationDto extends GenericDto { }
class VehicleInformationDto extends GenericDto { }
雖然我認為這絕對是將靜態型別添加到像 Javascript 這樣的語言中的正確選擇,其中物件是一個抓包的屬性,但它可能會導致一些微妙的問題:
interface Vec2 {
x: number
y: number
}
interface Vec3 {
x: number
y: number
z: number
}
const m = { x: 0, y: 0, z: "hello world" };
const n: Vec2 = m; // N.B. structurally m qualifies as Vec2!
function f(x: Vec2 | Vec3) {
if (x.z) return x.z.toFixed(2); // This fails if z is not a number!
}
f(n); // compiler must allow this call
在這里,我們正在做一些圖形編程,并且有 2D 和 3D 向量,但我們有一個問題:物件可以有額外的屬性,并且仍然在結構上限定,這導致了這種聯合型別的問題(聽起來很熟悉?)。
在您的特定情況下,答案是使用判別式輕松區分聯合中的相似型別:
interface FleetInformationDto extends GenericDto {
// N.B., fleet is a literal *type*, not a string literal
// *value*.
kind: 'fleet'
}
interface VehicleInformationDto extends GenericDto {
kind: 'vehicle'
}
在這里,我使用了字串,但任何唯一的編譯時常量(任何原始值或 的成員enum)都可以。此外,由于您沒有實體化您的類并將它們純粹用作型別,因此我將它們設為介面,但適用相同的原則。
操場
現在您可以清楚地看到“車隊”型別不可分配給“車輛”型別的錯誤。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/396834.html
上一篇:useEffect無限期運行
