在JavaScript中使用命名参数(基于TypeScript)

plupiseo  于 2022-12-14  发布在  TypeScript
关注(0)|答案(5)|浏览(165)

我在TypeScript中使用命名参数时遇到问题。我知道在TypeScript中使用命名参数的方式不受支持。
但我怎么能做到呢?
类型脚本:

SomeFunction(name1: boolean, name2: boolean, name3: boolean, name4: boolean) // Will occur only one time, so the change should be in TypeScript

JavaScript语言:

$(function () {
     ...SomeFunction({name1:false, name2:false, name3:false, name4:true}); // Will occur 100 times
});

我正在看(这没有工作):


我可以在TypeScript中做些什么,以便在JavaScript中使用命名参数?
我想知道的是,Visual Studio 2015在使用命名参数时没有显示语法错误,就像我在TypeScript中使用它一样。
附言:我使用TypeScript 2.1

efzxgjgh

efzxgjgh1#

JavaScript和TypeScript中都不存在真正的命名参数,但可以使用 destructuring 来模拟命名参数:

interface Names {
    name1: boolean
    name2: boolean
    name3: boolean
    name4: boolean
}

function myFunction({name1, name2, name3, name4}: Names) {
    // name1, etc. are boolean
}

注意:类型Names实际上是可选的。下面的JavaScript代码(无需键入)在TS中是有效的:

function myFunction({name1, name2, name3, name4}) {
    // name1, etc. are of type any
}
lfapxunr

lfapxunr2#

获得接近“命名参数”的唯一方法是使用单个对象参数:

type SomeFunctionParams = {
    name1: boolean;
    name2: boolean;
    name3: boolean;
    name4: boolean;
}

SomeFunction(params: SomeFunctionParams) { ... }

然后道:

$(function () {
    SomeFunction({
        name1:false,
        name2:false,
        name3:false,
        name4:true
    });
});
8fq7wneg

8fq7wneg3#

匿名接口

我只是想指出,您也可以在参数列表中声明不带名称的类型,如下所示,这样我们就不必输入interface myfuncArgs了。
它仍然迫使我重新输入每一个参数,这是一个痛苦,但我不知道如何避免目前。

const assert = require('assert')

function myfunc({
    myInt,
    myString,
  }: {
    myInt: number,
    myString?: string,
  }
) {
  return `${myInt} ${myString}`
}

assert.strictEqual(
  myfunc({
    myInt: 1,
    myString: 'abc',
  }),
  '1 abc'
)

assert.strictEqual(
  myfunc({
    myInt: 1,
  }),
  '1 undefined'
)

// Fails as desired since myInt is not optional and was not given.
//assert.strictEqual(
//  myfunc({
//    myString: 'abc',
//  }),
//  'unefined abc'
//)

// Fails as desired since wrong type of myInt.
//assert.strictEqual(
//  myfunc({
//    myInt: '1',
//    myString: 'abc',
//  }),
//  '1 abc'
//)

编译并运行:

npx tsc main.ts
node main.js

测试日期:

"dependencies": {
    "@types/node": "^16.11.13",
    "typescript": "^4.5.4"
  }

相关:

function myfunc({
  myInt: Number,
  myString?: String,
})

当有可选参数时,通常需要显式的interface

如果有任何props是可选的(以下示例就是这种情况,而且很可能是大多数“options”参数的情况),则您可能希望显式定义类型,如中所述:https://stackoverflow.com/a/42108988/895245,因为调用方很可能迟早会需要它来逐步构建options对象,相关内容如下:How do I dynamically assign properties to an object in TypeScript?
例如,考虑以下工作代码:

const assert = require('assert')

interface myfuncOpts {
  myInt: number,
  myString?: string,
}

function myfunc({
  myInt,
  myString,
}: myfuncOpts) {
  return `${myInt} ${myString}`
}

const opts: myfuncOpts = { myInt: 1 }
if (process.argv.length > 2) {
  opts.myString = 'abc'
}

assert.strictEqual(
  myfunc(opts),
  '1 abc'
)

如果我们已经定义了myfuncOpts内联,那么我们将无法执行const opts: myfuncOpts,然后opts.myString = 'abc'将失败,因为在:

const opts = { myInt: 1 }
if (process.argv.length > 2) {
  opts.myString = 'abc'
}

x1M5N1x的类型是从不包含x1M6N1x的初始化中推导出来的。
我希望TypeScript能实现一个系统,在那里你可以说“使用这样的函数的这样的参数的类型”。然后我们可以使用内联参数类型定义,但仍然以某种方式引用类型,这将是涅槃。

pzfprimi

pzfprimi4#

与发送值相比,这在可读性方面有了改进,而且它将值放在函数调用中,使其更具可读性,就像良好的老式命名参数一样。它不会遇到任何问题,如果你只是发送未标记的值,你就不会遇到这些问题,所以它是一个进步。

var includeIcons:boolean, includeChildren:boolean
await storageTank.save((includeIcons=false), (includeChildren=false))

对于单个开发人员的项目来说很好,但是对于大型项目来说不推荐,因为在大型项目中,开发人员之间可能不会就更改函数签名进行交流。

ewm0tg9j

ewm0tg9j5#

一个简单的解决方案是使用有意义地命名的局部变量:

var mungo: boolean=true, mary: boolean=true, and: boolean=true, midge: boolean=true;

zapOn(mungo, mary, and, midge);

这只是简单解决方案的第一步...遵循test-driven development的原则:测试失败,让它工作-测试绿色(此建议),并重构(如果需要,将局部变量放在一个对象中,并将其传递给函数)
如果在TypeScript中定义zapOn函数,则:zapOn({蒙戈,玛丽=假,蚊子,和}:电视接口){...},其中电视接口{玛丽?:布尔值,mungo:布尔值,以及:布尔值、Midge:boolean}并将电视对象= {玛丽:未定义,蒙戈:蒙戈,和:还有,米姬:midge} ie zapOn(tv)由于在函数参数级别的对象解构,函数中的变量/参数将正确排列......在"玛丽”参数的情况下,我们还设置了默认值false。

相关问题