繁体   English   中英

如何使用通用 object 修复“类型缺少类型中的属性”?

[英]How to fix 'Type is missing properties from type' with generic object?

考虑一个导出run function 的库,如下所示:

runner.ts

export type Parameters = { [key: string]: string };
type runner = (args: Parameters) => void;

export default function run(fn: runner, params: Parameters) {
    fn(params);
}

并在一个单独的文件中考虑以下代码: index.ts

import type { Parameters } from "./runner.ts";
import run from "./runner.ts";

type CustomParams = { hello: string };

function logGenericArgs(args: Parameters): void {
    console.log(args);
}

function logHelloFromArgs(args: CustomParams): void {
    console.log(args.hello);
}

run(logGenericArgs, { abc: "123" });
run(logHelloFromArgs, { hello: "123" });  /* Argument of type '(args: CustomParams) => void' is not assignable to parameter of type 'runner'.
  Types of parameters 'args' and 'args' are incompatible.
    Property 'hello' is missing in type 'Parameters' but required in type 'CustomParams'. ts(2345)
*/

为什么 TypeScript 抱怨不同的类型,当它们完全兼容时? 据我了解, Parameters类型是一个通用的 object,带有string键和string值; CustomParams的“hello”键完全符合Parameters的类型签名。

如何使“runner”库中的代码接受通用的 object 类型,并与其他兼容的类型很好地配合使用?
我不想使用类型unknownany ,因为那基本上没用。 我想要run function 的调用签名来表示args是 object,但我不想将args的类型仅限于该特定签名。
我也不想将CustomParams类型中的hello键指定为可选的,因为在CustomParams类型的使用中该键不应该是可选的 - 而且我不想在Parameters类型中添加键hello因为它不是必需的“runner”库的每个用例。

TypeScript 不知道params应该是fn的参数,但您可以轻松解决这个问题,但添加一个通用参数来关联两者:

type Params = { [key: string]: string };
type runner<P extends Params = Params> = (args: P) => void;

function run<P extends Params>(fn: runner<P>, params: P) {
    fn(params);
}

现在,当您调用自定义参数 function 时:

run(logHelloFromArgs, { hello: "123" });

推断为

function run<{
    hello: string;
}>(fn: runner<{
    hello: string;
}>, params: {
    hello: string;
}): void

这就是我们想要的。

操场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM