一种在泛型中禁用"type argument inference"的方法?



我希望为泛型提供默认值将优先于类型推断,但它没有:

// placeholder for a real express response.send
const sendResponse =  (x) => console.log(x);
function sendResult<T = never>(send: any, result: T) {
send(result);
}
// I want to use this always with a type
type Num = { x: number };
sendResult<Num>(sendResponse, { x: 1 });
sendResult<Num>(sendResponse, { x: 'sss' }); // correctly showing error
// When I don't supply type, I'd like an error.
// But, T gets inferred instead of defaulting to never... so, no error :-(
sendResult(sendResponse, {x: 1})

查看演示

有没有办法确保在未提供通用时引发错误?

打字稿版本:3.5.2

我不明白用例,因为禁用 TypeScript 用户期望的行为可能会导致混乱。 但你是老板。

在 microsoft/TypeScript#14829 上有一个现有的 GitHub 建议,允许开发人员指示不应将泛型类型参数的特定使用用于推理。 对此没有官方支持,但我认为我们可以在查看依赖于未解析的泛型类型参数的条件类型时利用编译器的行为来模拟它:

type NoInfer<T> = [T][T extends any ? 0 : never];

这本质上是对T的无操作,因为你插入的任何值(比如string)都会从另一边出来:[string][string extends any ? 0 : never]变成[string][0]变成string。 但是编译器看到T extends any,并决定将计算推迟到T解决之后。 特别是,它不能使用该值从中推断T

那么我们可以尝试

function sendResult<T = never>(send: any, result: NoInfer<T>) {
send(result);
}

看看它是如何表现的:

type Num = { x: number };
sendResult<Num>(sendResponse, { x: 1 }); // okay
sendResult<Num>(sendResponse, { x: "sss" }); // error
sendResult(sendResponse, { x: 1 }); // error

前两种情况可以根据需要工作,因为指定Num会给T一个确定的值,而NoInfer<Num>只是Num。 在最后一种情况下,编译器确实没有可行的推理站点T因此它必须回退到默认never,你会得到你想要的错误。

操场链接到代码

所以这就像你想要的那样工作,但请记住,你可能想重新考虑这个想法,因为得到这个错误的人可能会对他们应该做什么来让错误消失感到困惑。 人们依赖于类型推断,因此如果您继续这样做,您将需要一些出色的文档。

相关内容

最新更新