我正在尝试将对象(Item接口)投射到其派生接口(FileItem或FolderItem)
interface Item {
id: number;
name: string;
}
interface FileItem extends Item {
size: number;
}
interface FolderItem extends Item {
parent_id: number;
}
const files: FileItem[] = [ {id: 1, name: 'file name 1', size: 1024 } ];
const folders: FolderItem[] = [ {id:1, name: 'folder 1', parent_id: 0} ];
const items = new Array<Item>(...files, ...folders);
items.forEach(i => {
const isFile = i as FileItem;
if (isFile) {
writeLog('its a file');
}
else writeLog('its a folder');
})
在foreach循环中,打字稿将所有项目都强制转换为FileItem,这是错误的,因为它应该强制转换为FileItem和FolderItem,请查看demo
这是打字稿中的类型转换的工作方式吗?如何转换为正确的界面。
谢谢
答案 0 :(得分:0)
这不是Typescript中的类型转换的工作方式。在编译期间,所有类型都被剥离,因此您的代码将最终如下所示:
const files = [ {id: 1, name: 'file name 1', size: 1024 } ];
const folders = [ {id:1, name: 'folder 1', parent_id: 0} ];
const items = new Array(...files, ...folders);
items.forEach(i => {
const isFile = i;
if (isFile) {
writeLog('its a file');
}
else writeLog('its a folder');
})
isFile
永远是真实的,因为i
是真实的。
要获得所需的服务,您需要使用type guard。例如:
function isFile(item: Item): item is FileItem {
return (item as FileItem).size !== undefined;
}
这将检查Item
是否具有属性size
。如果是,则必须为FileItem
。您可以这样使用它:
items.forEach(i => {
if (isFile(i)) {
writeLog('its a file');
}
else writeLog('its a folder');
})
完整代码:
interface Item {
id: number;
name: string;
}
interface FileItem extends Item {
size: number;
}
interface FolderItem extends Item {
parent_id: number;
}
function isFile(item: Item): item is FileItem {
return (item as FileItem).size !== undefined;
}
const files: FileItem[] = [ {id: 1, name: 'file name 1', size: 1024 } ];
const folders: FolderItem[] = [ {id:1, name: 'folder 1', parent_id: 0} ];
const items = new Array<Item>(...files, ...folders);
items.forEach(i => {
if (isFile(i)) {
writeLog('its a file');
}
else writeLog('its a folder');
})
此外,您为什么使用new Array
?您可以这样做:
const items: Item[] = [...files, ...folders]