【问题标题】:Defining TypeScript variable type function or string定义 TypeScript 变量类型函数或字符串
【发布时间】:2016-07-17 03:29:55
【问题描述】:

我有这个界面:

interface IParameters {
    form: number;
    field: string;
    ...
}

我希望formproperty 是数字或函数,field 是字符串或函数。

我尝试这样的事情:

interface IParameters {
    form: number | Function;
    field: string | Function;
    ...
}

我需要这个,因为在我的代码中我使用这样的变量:

var form = (typeof _oParameters.form === "function" ? _oParameters.form() : _oParameters.form);
var field = (typeof _oParameters.field === "function" ? _oParameters.field() : _oParameters.field);

我不想在我的所有代码中将此变量从字符串/数字更改为默认函数,并防止将此变量设置为其他类型。

但如果我尝试调用这两个变量之一,如函数:

var param:IParameters;
param.form();
...

我收到此错误:

无法调用类型缺少调用签名的表达式。

param.form = 12; 有效。

我找到的唯一解决方案是将formfield 声明为any 类型。

没有any类型的其他方式来定义这个变量吗?

【问题讨论】:

    标签: function types typescript


    【解决方案1】:

    更新
    这种行为似乎是 TypeScript 的问题#3812
    根据指定的里程碑,它将作为 TypeScript 2.0 的一部分进行修复。

    原答案

    您可以使用 instanceof 作为类型保护,例如

    var field = (_oParameters.field instanceof Function ? _oParameters.field() : _oParameters.field);
    

    【讨论】:

    • 如果我使用你的代码,我会得到同样的错误Cannot invoke an expression whose type lacks a call signature. 这个定义form: number | Function;
    • 你是对的。那似乎是带有 TypeScript 的issue。它有望在 v2.0 中修复。
    • 现在修复了吗?
    【解决方案2】:

    也许如果您使用调用签名而不是 Function 来定义联合类型,就像这样...

    interface IParameters {
        // form is of type function that returns number, or number literal.
        form: () => number | number;
    
        // field is of type function that returns a string, or string literal.
        field: () => string | string;
    }
    
    class Foo {
        constructor (param: IParameters) {
            var x = typeof param.form === "number" ? param.form : param.form();
            var y = typeof param.field === "string" ? param.field : param.field();
        }
    }
    

    在这里,我仍在使用 typeof 检查 formfield,但是 TypeScript 很高兴它是函数调用或值。

    【讨论】:

      【解决方案3】:

      如果您尝试使用 seriesOne 中的代码,您会注意到,您不能为form(或field)分配一个不是函数的值。 你会得到一个
      Type '{ form: string; }' is not assignable to type 'IParameters'. Types of property 'form' are incompatible. Type 'string' is not assignable to type '() => string'.

      我发现使用form: (() => string) | string; 可以解决这个问题。

      您可以在the typescript playground 尝试代码。

      工作样本:

          interface IParameters {
              form: (() => string) | string;
          }
      
          function strFunct(): string {
              return 'Hello TypeScript';
          }
      
          function test() {
              let paramA: IParameters = {
                  form: strFunct
              }
      
              let paramB: IParameters = {
                  form: 'Hello stackoverflow'
              }
          }
      
          class Foo {
              constructor(param: IParameters) {
                  var x = typeof param.form === 'string' ? param.form : param.form();
              }
          }
      

      【讨论】:

      • 哇! IParameters 上的函数之间的括号起到了作用!!
      • 这个。奇怪的是,如果您编写 ()=>string|string 编译器将允许它,但使用它的类只会期望 ()=>string 并且不允许传递字符串文字。另一方面,如果您颠倒顺序并编写 string|()=>string 打字稿将不会解析它。将括号放在调用签名周围可以解决这两种情况。
      猜你喜欢
      • 2019-02-04
      • 2020-12-11
      • 1970-01-01
      • 2019-03-20
      • 2021-11-26
      • 1970-01-01
      • 1970-01-01
      • 2016-08-31
      • 1970-01-01
      相关资源
      最近更新 更多