简体   繁体   English

如何有条件地在 typescript 中设置 function 参数类型?

[英]How to conditionally set a function argument type in typescript?

I have a generic function I need to call in 2 places我有一个通用的 function 我需要在 2 个地方打电话

const functionA = (arg1, deleteFunction) => {
 deleteFunction(arg1)
}

when I call it in the two different places I pass in a different deleteFunction each time.当我在两个不同的地方调用它时,我每次都传入一个不同的deleteFunction these deleteFunctions then update redux but they require different types so I'm getting errors这些deleteFunctions然后更新 redux 但它们需要不同的类型,所以我收到错误

I was wondering if for arg1 I could specify what type it should be based on properties it contains.我想知道对于arg1我是否可以根据它包含的属性指定它应该是什么类型。 something like this像这样的东西

const functionA = (arg1: arg1.hasSomeProperty ? Arg1Types : Arg1OtherType, deleteFunction) => {
 deleteFunction(arg1)
}

obviously this doesn't work but the 2 deleteFunctions have different types (one has Arg1Types the other has Arg1OtherTypes显然这不起作用,但 2 个 deleteFunctions 有不同的类型(一个有Arg1Types另一个有Arg1OtherTypes

might be going about it in completely the wrong way.可能会以完全错误的方式进行。 any ideas?有任何想法吗?

You can use a function overload, either using overload syntax with the function keyword, or using an interface with const an an arrow function as in your question.您可以使用 function 重载,或者使用带有function关键字的重载语法,或者在您的问题中使用带有const和箭头 function 的接口。

Overload syntax:重载语法:

function functionA(arg: Arg1Type, deleteFunction: (arg: Arg1Type) => void): void;
function functionA(arg: Arg1OtherType, deleteFunction: (arg: Arg1OtherType) => void): void;
function functionA(arg: any, deleteFunction: (arg: any) => void): void {
    deleteFunction(arg);
}

Playground Link 游乐场链接

A function interface with const an an arrow function:带有const和箭头 function 的 function 接口:

interface FunctionA {
    (arg: Arg1Type, deleteFunction: (arg: Arg1Type) => void): void;
    (arg: Arg1OtherType, deleteFunction: (arg: Arg1OtherType) => void): void;
}

const functionA: FunctionA = (arg: any, deleteFunction: (arg: any) => void): void => {
    deleteFunction(arg);
};

Playground link 游乐场链接

In both cases, if Arg1Type is string and Arg1OtherType is number (for example), these calls work:在这两种情况下,如果Arg1Typestring并且Arg1OtherTypenumber (例如),则这些调用有效:

functionA("foo", (id) => {
    // ...do the deletion...
});

functionA(42, (id) => {
    // ...do the deletion...
});

...and these don't: ...而这些不会:

// Error: No overload matches this call.
// (because the types don't match)
functionA("foo", (id: number) => {
    // ...do the deletion...
    console.log(id);
});

// Error: No overload matches this call.
// (because no overload takes an object)
functionA({}, (id) => {
    // ...do the deletion...
    console.log(id);
});

And in both cases, only the overload signatures (the first two) will be shown by IDEs, etc.;在这两种情况下,IDE 等只会显示重载签名(前两个); the implementation signature isn't.实现签名不是。

在此处输入图像描述

在此处输入图像描述

In a comment you've said:在评论中你说:

...how the invoking of this functions knows which types to use? ...调用此函数如何知道要使用哪些类型? Arg1Type and Arg1OtherType are both objects but inside these objects, the types are differents for each property. Arg1Type 和 Arg1OtherType 都是对象,但在这些对象内部,每个属性的类型不同。 ... I'd like to understand the conditional part a bit more ...我想进一步了解条件部分

TypeScript will infer the correct overload to use based on the types of the arguments. TypeScript 将根据 arguments 的类型推断要使用的正确过载。 In my examples, the types are string and number .在我的示例中,类型是stringnumber When I started with functionA("foo", TypeScript could tell that I was using the string overload and will only allow a function that accepts a string. When I started with functionA(42, TypeScript could tell I was using the number overload and will only allow a function that accepts a number. When I started with functionA("foo", TypeScript could tell that I was using the string overload and will only allow a function that accepts a string. When I started with functionA(42, TypeScript could tell I was using the number overload and will只允许接受数字的 function。

That's fine with objects with different shapes as well:对于具有不同形状的对象也可以这样:

interface Arg1Type {
    prop: string;
}
interface Arg1OtherType {
    prop: number;
}

functionA({"prop": "foo"}, (obj) => {
    // ...do the deletion...
    console.log(obj);
});

functionA({"prop": 42}, (obj) => {
    // ...do the deletion...
    console.log(obj);
});

Playground Link 游乐场链接

type A = string
type B = number
type Arg1 = A | B
const functionA = (arg1: Arg1, deleteFunc: (arg1: Arg1) => void): void {
 deleteFunc(arg1);
}

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

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