传入函数的对象的Typescript默认参数

yxyvkwin  于 2023-08-08  发布在  TypeScript
关注(0)|答案(5)|浏览(120)

我想以类似于标量值的方式初始化传递到函数中的对象,例如:

someFunction(myValue: number = 5) {  }

字符串
所以,我保留了 * 类型和默认值。我想将类似的结构应用于以下内容:

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


如果我直接使用简单的复制粘贴解决方案:

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


每种初始化方法都会给出TypeScript错误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艺术的奖励积分:)

hc8w905p

hc8w905p1#

如果你利用描述,你可以减少很多重复的代码,但是重要的是要意识到这些差异。这是我通常使用的模式。

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

字符串
这个函数的签名被正确推断为function fun({ val1, val2 }?: { val1?: number; val2?: number; }): number
然而,重要的是要注意,这个函数在几个重要方面与原始函数不同。

  1. fun({ val1: 2 })将导致val2仍为默认值2
    1.如果你需要一个必需的参数(如果你提供了任何东西,你必须提供它),你必须返回到指定一切,这很快变得更加混乱,因为你在两个位置有初始化器。这可以通过使用接口来描述类型来缓解。
interface Args {
    val1?: number
    val2?: number
    val3: string
}

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

cnwbcb6i

cnwbcb6i2#

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

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

字符串
这种解决方案的问题是,参数上的所有属性都是必需的,因此即使它们的值未定义,也必须指定它们。
为了解决这个问题,我们可以定义一个helper函数,它返回一个所有项都标记为可选的类型:

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
})

hmmo2u0o

hmmo2u0o3#

看起来像对象文字作为一个参数与默认值的行为不同,作为比较标量函数参数。
类型文本属性不能有初始值设定项
键入对象时尝试提供值时会发生此错误。因此,为了摆脱这种情况,我们可以将类型与默认值分开。

function someFunction({val1 = 5, val2 = 8} : { val1?: number; val2?: number }) {
    console.log(val1);
    console.log(val2);
}

someFunction({}) // 👉️ 5, 8

字符串

zpgglvta

zpgglvta4#

你已经给出了答案。TypeScript不能做更多的事情,因为它在运行时不工作,并且会生成和分配默认值:在运行时。默认参数值是ECMAScript功能,而不是TypeScript功能。
如果你担心代码污染,你可以做一些类似的事情

type FunctionOptions = {
    val1: number,
    val2: number
}

// const assertion to create readonly values
const defaultOptions = {
    val1: 5,
    val2: 10
} as const;

function someFunction(myObj: FunctionOptions = defaultOptions) {
    // ...
}

字符串
当然,由于前面提到的原因,这些默认值不会记录在代码中。您可以使用JSDoc@default来提供这类提示。

type FunctionOptions = {
    /** @default 5 */
    val1: number,
    /** @default 10 */
    val2: number
}

y4ekin9u

y4ekin9u5#

你可以使用它的接口:

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

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

字符串
我希望我能正确理解你的问题并帮助你:)和MB。这个:https://www.typescriptlang.org/docs/handbook/interfaces.html,所以使用接口是很好的解决方案.

相关问题