4 回答
TA贡献1808条经验 获得超4个赞
您的问题是,它cell的类型可能CellA不具有该属性date(因此您收到的错误消息)。请注意,反之亦然,即cell也不具有该属性text。
潜在的解决方案
1.使用交叉类型
如果cell应该是两者的组合CellA,CellB那么你可以制作celltype CellA & CellB。例如:
type CellC = CellA & CellB
const cell: CellC = { date: new Date(), text: 'Hello!' }
const { date, text }
console.log(date, text)
2.使用类型守卫:Playground
如果您有一个值需要在运行时进行类型检查,则可以使用用户定义的类型保护。例如,如果您有一个cell
在运行时不知道其类型的变量:
const cell = { text: 'Hello!' } // unknown type
function isCellA(obj: any): obj is CellA {
if(!obj) return false
if(!obj.text) return false
if(typeof obj.text !== 'string') return false
return true
}
if(isCellA(cell)) {
// at this point the compiler recognizes that cell
// is of type CellA
console.log(cell.text)
}
如果您需要在运行时进行类型检查,这可能是您的最佳选择。它可以维护类型安全,并有助于减少运行时错误(如果cell确实不是您所期望的那样)。
3.扩展另一个接口
这与解决方案#1 非常相似。如果CellA和CellB应该共享一些属性,那么它们之一可以扩展另一个,或者它们可以扩展一个公共接口。例如:
interface Cell {
date: Date
}
interface CellC extends Cell {
text: string
}
4:React组件组成
如果您特别遇到此问题,React(如您的评论所述),您可以考虑使用一个单独的组件来返回每种单元格类型的主要组件。例子:
function ACell({ data }: { data: CellA } ) {
return <Cell>{data.text}<Cell>
}
function BCell({ data }: { data: CellB } ) {
return <Cell>{data.date.toString()}<Cell>
}
function Cell({ children }: { children: string }) {
return <p>{children}</p>
}
也许这不符合您的特定用例,但类似的东西可能有助于分离组件之间每种类型单元的逻辑,以及Cell例如与第三个组件共享公共逻辑。
TA贡献1842条经验 获得超21个赞
您这样做的方式是做出cell同时具有date和text的假设。但是,当您指定cell为 aCellA或CellB类型时,打字稿会抱怨,因为每种类型都缺少其中一个属性。
您可以只分配可选属性吗?像这样:
interface CellType {
date?: Date,
text?: string
}
const { date, text } = cell as CellType
或者,如果您确实想强制 acell严格成为这些类型之一,我会在定义变量时执行此操作:
interface CellA {
text: string;
}
interface CellB {
date: Date;
}
type CellType = CellA | CellB
const cell: CellType = { ... }
TA贡献1884条经验 获得超4个赞
通常,当您想要在 Typescript 中的参数/变量类型上切换控制流时,您需要使用可区分联合:
interface CellA {
text: string,
kind: "CellA",
}
interface CellB {
date: Date,
kind: "CellB",
}
type Cell = CellA | CellB;
function takesACell(cell: Cell) {
switch(cell.kind) {
case "CellA":
console.log("Got an A");
cell.text; // no type error
break;
case "CellB":
console.log("Got a B");
cell.date; // no type error
break;
}
}
编译器将这种模式理解为您正在根据运行时类型进行分派,但它仍然会提供编译时类型安全性,因为您不能只传递不合格的值。
TA贡献1951条经验 获得超3个赞
如果可能的话,您可以扩展接口以接受任何其他值。例如:
export interface CellA {
text?: string;
[index: string]: any;
}
export interface CellB {
date?: Date;
[index: string]: any;
}
添加回答
举报