【发布时间】:2018-06-13 08:02:22
【问题描述】:
上下文:
我正在尝试编写一个函数,该函数将允许该函数的用户使用 no typescript type assertions(只是简单的旧 javascript 语法)定义某种类型。基本上,我正在尝试编写类似 React 的 PropTypes 的东西,但我想将使用这些“PropTypes”定义的类型映射到可以使用 typescript 强制执行的类型。
也许通过查看代码更容易理解我想要做什么。 defineFunction 下面是一个函数,它返回一个函数,该函数接受由“PropTypes”`定义的对象。
interface PropType<T> { isOptional: PropType<T | undefined> }
type V<Props> = {[K in keyof Props]: PropType<Props[K]>};
interface PropTypes {
string: PropType<string>,
number: PropType<number>,
bool: PropType<boolean>,
shape: <R>(definer: (types: PropTypes) => V<R>) => PropType<R>
}
// the only purpose of this function is to capture the type and map it appropriately
// it does do anything else
function defineFunction<Props, R>(props: (types: PropTypes) => V<Props>, func: (prop: Props) => R) {
return func;
}
// define a function
const myFunction = defineFunction(
// this is the interface definition that will be mapped
// to the actual required props of the function
types => ({
stringParam: types.string,
optionalNumberParam: types.number.isOptional,
objectParam: types.shape(types => ({
nestedParam: types.string,
}))
}),
// this is the function definition. the type of `props`
// is the result of the mapped type above
props => {
props.objectParam.nestedParam
return props.stringParam;
}
);
// use function
myFunction({
stringParam: '',
optionalNumberParam: 0,
objectParam: {
nestedParam: ''
}
});
这是通过将鼠标悬停在 VS Code 中的类型上找到的 myFunction 的结果类型:
const myFunction: (prop: {
stringParam: string;
optionalNumberParam: number | undefined;
objectParam: {
nestedParam: string;
};
}) => string
问题:
上面的代码有一个问题——optionalNumberParam 被正确定义为 number | undefined 但它实际上不是可选的!
如果我省略了optionalNumberParam,打字稿编译器会骂我。
有没有断言一个类型是可选的,而不仅仅是T | undefined?
回复cale_b的评论:
只是一个想法 - 你尝试过 optionalNumberParam 吗?:types.number.isOptional
是的,这是无效的语法:
澄清一下,这个defineFunction 应该让用户使用no typescript type assertions定义一个类型——而不是所有东西都应该使用映射类型来推断。 ? 只是打字稿。我正在尝试编写此函数,以便 - 从理论上讲 - javascript 用户可以定义 proptypes 并且仍然让 typescript 编译器强制执行这些 proptypes。
【问题讨论】:
-
@cale_b 查看更新后的答案。在那里添加了一个屏幕截图,因为我无法在 cmets 中添加一个
-
很好的说明。谢谢,祝你好运!在这一点上超出我的深度...... :)
-
我没有给你很好的解决方案;您可能会发现需要指定两种对象字面量:一种用于必需参数,另一种用于可选参数,其结果是两种映射类型的交集(一种带问号,一种不带问号)。
-
@jcalz 对于解决方法来说这不是一个坏主意。我开始认为我所要求的还不可能。我将在 typescript github 上打开一个问题,一旦完成提案,我将链接到它
-
@jcalz 这是我刚刚提交的提案:github.com/Microsoft/TypeScript/issues/20984
标签: javascript typescript mapped-types