【问题标题】:How to make function argument that is generic object consuming two functions with one type or void in Typescript如何使作为通用对象的函数参数在 Typescript 中使用一种类型或 void 的两个函数
【发布时间】:2017-06-14 01:50:20
【问题描述】:

我在打字稿中有以下情况:

type Matcher<T, U> = {
  First: (arg: T) => U,
  Second: () => U
};

class Main<T> {    
  constructor(private value: T) {
  }

  match<U>(matcher: Matcher<T, U>): U {
    return this.value
      ? matcher.First(this.value)
      : matcher.Second();
  }
}

const main = new Main(10);

const res = main.match({ // there is a problem
  First: v => v + 10,
  Second: () => console.log()
});

所以我有一个对象,用户必须将其传递给类实例的match 方法。该对象应包含两个函数:FirstSecond。该函数返回一种类型的值(例如number)或一种类型的值+void(例如number+void),但没有别的。不能有 string + number 类型。

此代码失败并出现错误

The type argument for type parameter 'U' cannot be inferred from the usage. Consider specifying the type arguments explicitly. 
Type argument candidat 'void' is not a valid type argument because it is not a supertype of candidate 'number'.

我明白为什么会出现这个错误(U 是单一类型,但是函数有两种不同的类型,它们不能合并等等),但是我该如何解决这个问题呢?我需要:

  • 严格类型,所以不应该有any类型
  • 允许两个函数只使用一种类型,或者void 在一个或两个中使用。 numberstring 作为返回类型是不允许的。

是否可以使用 typescript 类型系统?

【问题讨论】:

    标签: typescript typescript-typings


    【解决方案1】:

    你可以使用union types:

    type Matcher<T, U> = {
        First: (arg: T) => U;
        Second: () => U | void
    };
    

    我只在第二个函数中添加了void,但您也可以在第一个函数中添加它。

    但是你将需要match 方法来返回| void

    match<U>(matcher: Matcher<T, U>): U | void {
        return this.value
            ? matcher.First(this.value)
            : matcher.Second();
    }
    

    (code in playground)


    编辑

    如果我理解正确,那么这可能会有所帮助:

    type Matcher<T, U> = {
        First: (arg: T) => U;
        Second: () => U;
    };
    
    type MatcherOne<T, U> = {
        First: (arg: T) => void;
        Second: () => U;
    };
    
    type MatcherTwo<T, U> = {
        First: (arg: T) => U;
        Second: () => void;
    };
    
    class Main<T> {
        constructor(private value: T) { }
    
        match<U>(matcher: Matcher<T, U>): U;
        match<U>(matcher: MatcherOne<T, U>): U | void;
        match<U>(matcher: MatcherTwo<T, U>): U | void;
        match<U>(matcher: Matcher<T, U> | MatcherOne<T, U> | MatcherTwo<T, U>): U | void {
            return this.value
                ? matcher.First(this.value)
                : matcher.Second();
        }
    }
    

    (code in playground)

    【讨论】:

    • 它仍然抱怨无法从使用中推断类型参数。
    • 添加了一个符合规范的游乐场版本的链接。
    • 这可能是一些误解。我希望匹配器中的两个函数都能够是 void 或相同类型。所以我只是在第一个和第二个函数中添加了void作为第二个类型,编译失败。
    • 现在可以了吗?还是您还有问题?
    • 我需要一个允许用户发送对象{ First: void, Second: number }{ First: string, Second: void }{ First: array, Second: array } 的对象,因此仅在SecondFirst 函数上启用void 是不够的.
    猜你喜欢
    • 2019-09-30
    • 2013-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-09
    • 2010-09-22
    • 2021-12-15
    相关资源
    最近更新 更多