这个标题不好意思,我真的不知道它的名字
我正在写一个mapper函数,它在React中接受一个类型并返回一个组件,并对如何为它编写返回类型感到困惑。
基本上每个组件都接受{data},这是IBlock
的子类型。
// simulate React
interface FunctionComponent<P = {}> {
(props: P): string;
}
type FC<P = {}> = FunctionComponent<P>;
// actual code
export enum BlockType {
'HEADER'='header',
'HEADING'='heading',
'GROUP'='group',
'CARD'='card',
'IMAGE'='image',
}
export interface IBlock {
type: BlockType;
id?: string;
elements?: IBlock[];
[key: string]: unknown;
}
export interface IHeader extends IBlock {
type: BlockType.HEADER;
title: string;
}
export interface IHeading extends IBlock {
type: BlockType.HEADING;
paragraph: string;
}
export interface IBlockComponentProps<T extends IBlock> {
data: T,
children?: string[]
}
const Placeholder: FC<IBlockComponentProps<IBlock>> = ({data}) => {
return data.type;
};
const Header: FC<IBlockComponentProps<IHeader>> = ({data}) => {
return data.title;
}
const Heading: FC<IBlockComponentProps<IHeading>> = ({data}) => {
return data.paragraph;
}
function typeToComp(type: BlockType): FC<IBlockComponentProps<any>> {
const map = {
[BlockType.HEADER as string]: Header,
[BlockType.HEADING as string]: Heading
};
return map[type] ?? Placeholder;
};
我的问题是:这里应该用什么代替any
?我想说:每一个类型/接口都是IBlock
的子类型
function typeToComp(type: BlockType): FC<IBlockComponentProps<any>>
如果我把IBlock
放在那里,它会抱怨每个组件接受它的子类型,我不能(或不想)把每个子类型在那里。
请帮助。谢谢你
拥有函数的一般超类型并不是真正的类型安全。您的函数期望被传递IBlock
的子类型。将它们赋值给类似于FC<IBlockComponentProps<IBlock>>
的东西,将允许使用类型为IBlock
的东西调用组件,即使它们期望的是IBlock
的子类型。
你应该考虑重写这个函数,使它返回给定类型T
的正确的组件类型,而不仅仅是一些一般的类型。
function typeToComp<T extends BlockType>(type: T) {
const map = {
[BlockType.HEADER]: Header,
[BlockType.HEADING]: Heading
};
return (map[type as keyof typeof map] ?? Placeholder) as (
typeof map & {
[K in Exclude<BlockType, keyof typeof map>]: typeof Placeholder
}
)[T]
};
可以构造一个可索引的类型,它计算被T
索引后的返回类型。如果T
是map
的key,则返回typeof map[T]
对应的组件类型。如果不是,则返回typeof Placeholder
。