传递给函数

时间:2018-03-30 06:40:43

标签: typescript

我希望以与标量值类似的方式初始化传递给函数的对象,例如:

someFunction(myValue: number = 5) {  }

所以,我保持两种类型和默认值。我想将类似的结构应用于以下内容:

someFunction(myObj: {val1: number, val2: number}) { }

如果我直接前进并且只是做一些没有脑子的复制粘贴解决方案:

someFunction(myObj: {val1: number = 5, val2: number = 10}) {}  

每种初始化方法都会提供TypeScript erorr A type literal property cannot have an initializer.。好吧,明白了,我无法将类型文字与初始化混合在一起。使用类比,我们有:

someFunction(myValue: number = 5) {  }
             ^^^^^^^  ^^^^^^   ^^
              |         |       +-- Initialization value
              |         +-- Type literal
              +-- Parameter name

类似地:

someFunction(myObj: {val1: number, val2: number} = {val1: 5, val2: 10}) {}
             ^^^^^   ^^^^^^^^^^^^^^^^^^^^^^^^^^     ^^^^^^^^^^^^^^^^^^
              |         |                              +-- Initialization
              |         +-- Type literal
              +-- Parameter name

解决方案是使用更详细的语法:

someFunction(myObj: {val1: number, val2: number} = {val1: 5, val2: 10}) {}

问题是有可能,有一个蛋糕并吃它:有标量值默认值定义(number = 5)和带对象定义的完整类型控制的简洁语法?

PS我请求ASCII艺术的奖励积分:)

3 个答案:

答案 0 :(得分:1)

没有内置方法可以做到这一点。最简单的解决方案是让编译器根据默认值推断参数类型:

function someFunction(myObj = { val1: 5, val2: 10 }) { }

此解决方案的问题是参数需要所有属性,因此即使它们的值未定义,也必须指定它们。

为了解决这个问题,我们可以定义一个辅助函数,它返回一个所有项都标记为可选的类型:

function params<T>(o: T): Partial<T> {
    return o;
}
function someFunction2(myObj = params({ val1: 5, val2: 10, otherValueWithoutDefault: null as number })) { } 

或支持可选参数和必需参数的版本:

function params<TRequired>() : <TOptional>(o: TOptional) => Partial<TOptional> & TRequired
function params<TOptional>(o: TOptional) : Partial<TOptional> 
function params<T>(o?: T): Partial<T> | (<TOptional>(o: TOptional) => Partial<TOptional> & T) {
    if(o != null) {
        return o;
    } else {
        return function(o : any) { return o; } as any
    }
}
function someFunction2(myObj = params<{ required: boolean}>()({ val1: 5, val2: 10})) { }

someFunction2({
    required: true,
    val1: 0
})

答案 1 :(得分:0)

您可以使用界面:

interface myObj {
  name: string;
  age: number;
  anyValue?: any;
}

const someFunction = (myObj: myObj) => {
  // method body
};

我希望我理解你的问题并帮助你:) 和mb。这个:https://www.typescriptlang.org/docs/handbook/interfaces.html, 所以使用界面是很好的解决方案。

答案 2 :(得分:0)

如果您利用解构,可以减少大量重复代码,但重要的是要注意这些差异。这是我通常使用的模式。

function fun({ val1 = 1, val2 = 2 } = {}) {
    return val1 + val2
}

此功能的签名正确推断为function fun({ val1, val2 }?: { val1?: number; val2?: number; }): number

但重要的是要注意,此功能在几个重要方面与原始功能不同。

  1. fun({ val1: 2 })会导致val2仍然是默认值,2

  2. 如果你需要一个必需的参数(如果你提供任何东西,你必须提供它),你必须回到指定所有东西,由于你在两个位置有初始化器,这很快变得更加混乱。这可以通过使用接口来描述类型来缓解。

    interface Args {
        val1?: number
        val2?: number
        val3: string
    }
    
    function fun({ val1 = 1, val2 = 2, val3 }: Args = { val3: ' ' }) {
        return val3.repeat(val1 + val2)
    }