Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如果多次传递另一个参数,则Typescript需要参数_Typescript - Fatal编程技术网

如果多次传递另一个参数,则Typescript需要参数

如果多次传递另一个参数,则Typescript需要参数,typescript,Typescript,我正在尝试做一个分布式联合类型,其中传递一个键,需要其他键 接口基本参数{ 标题:字符串 } 接口函数{ 启用寻呼机:true 限制:数目 计数:数字 } 类型FuncArgs=(FuncPagerArgs和BaseArgs)| BaseArgs; 函数func(参数:FuncArgs){ 如果(args中的“enablePager”){ 寻呼机({limit:args.limit,count:args.count}); } } 接口页面{ 限制:数目 计数:数字 } 函数寻呼机(args:Pa

我正在尝试做一个分布式联合类型,其中传递一个键,需要其他键

接口基本参数{
标题:字符串
}
接口函数{
启用寻呼机:true
限制:数目
计数:数字
}
类型FuncArgs=(FuncPagerArgs和BaseArgs)| BaseArgs;
函数func(参数:FuncArgs){
如果(args中的“enablePager”){
寻呼机({limit:args.limit,count:args.count});
}
}
接口页面{
限制:数目
计数:数字
}
函数寻呼机(args:PagerArgs){
}
func({
标题:“某物”,
启用寻呼机:true
})


对我来说,该代码不应该通过验证,因为我在传递enablePager时调用了
func
,但当
enablePager
为true时,我没有通过
limit
count
这两个都是必需的。在我的现实世界示例中,我尝试对3或4个不同的特性布尔值执行此模式,每个特性布尔值都将改变契约以需要更多字段。不幸的是,我甚至不能使用第一个布尔特性,更不用说多个了。

我们在这里看到的问题与联合元素之间没有适当的区别有关。我们在两个成员之间有重叠
(funcpagerags&BaseArgs)| BaseArgs
,重叠相等
BaseArgs
。非常重要的是:

在比较函数参数的类型时,如果源参数可分配给目标参数,则分配成功,反之亦然

这意味着什么-如果我们的类型可以分配给想要的类型,或者想要的类型可以分配给我们的参数类型,那么您可以传递它。考虑测试:

type ArgType = {
    title: "something",
    enablePager: true
}
type IsAssignable = ArgType extends FuncArgs ? true : false; // true, can be passed
所以您要传递的类型是可分配给想要的类型的,那么TS允许传递它。不要问我为什么,这是设计决策,你可以把它理解为一种妥协,更严格会阻止许多想要的行为,至少我在上面链接的TS文档中已经说明了这一点。可以肯定的是,现在代码中存在的问题将使我们成为运行时错误

为了解决这个问题,我们需要创建一个没有重叠的适当的有歧视的联盟

interface BaseArgs {
    title: string
}

interface OnlyTitle extends BaseArgs {
    kind: 'TITLE'
}

interface FuncPagerArgs extends BaseArgs {
    kind: 'PAGER'
    enablePager: true
    limit: number
    count: number
}

type FuncArgs = OnlyTitle | FuncPagerArgs;

function func(args: FuncArgs) {
    if (args.kind === 'PAGER') {
        pager({ limit: args.limit, count: args.count });
    }
}

interface PagerArgs {
    limit: number
    count: number
}

function pager(args: PagerArgs) {

}

func({
    kind: "TITLE",
    enablePager: true
}) // error 

func({
    kind: "TITLE",
    title: 'title'
}) // correct 
我所做的是以
kind
属性的形式,它将允许在适当的成员上不存在任何重叠。这意味着现在您只能使用或一个或另一个变体,类型永远不会重叠

在评论之后编辑 作者在评论中表示,他需要将所有选项组合在一起,但当某项功能启用时,所有与该功能相关的选项都应包含在内。这种结构我们可以通过分组分离选项+加入选项来实现。考虑:

interface Base {
    title: string
}
interface Pager  {
  pager?: {
    limit: number
    count: number
  }  
}

interface Sort {
  sorter?: {
    columns: string[] // example property
  }  
}

type Options = Pager & Sort & Base;

function func(args: Options) {
    if (args.pager) {
        pager({ limit: args.pager.limit, count: args.pager.count });
    }
    if (args.sorter) {
       sorter(args.sorter.columns)
    }
}

func({
  title: 'title',
  pager: {count: 2, limit: 10} // all fields its ok
})


func({
  title: 'title',
  pager: {count: 2} // error limit is missing
})


现在我们可以将
pager
sorter
放在一起,当您有
pager
时,您需要根据需要放置所有与之相关的选项。

我们在这里看到的问题与联合元素之间没有适当的区别有关。我们在两个成员之间有重叠
(funcpagerags&BaseArgs)| BaseArgs
,重叠相等
BaseArgs
。非常重要的是:

在比较函数参数的类型时,如果源参数可分配给目标参数,则分配成功,反之亦然

这意味着什么-如果我们的类型可以分配给想要的类型,或者想要的类型可以分配给我们的参数类型,那么您可以传递它。考虑测试:

type ArgType = {
    title: "something",
    enablePager: true
}
type IsAssignable = ArgType extends FuncArgs ? true : false; // true, can be passed
所以您要传递的类型是可分配给想要的类型的,那么TS允许传递它。不要问我为什么,这是设计决策,你可以把它理解为一种妥协,更严格会阻止许多想要的行为,至少我在上面链接的TS文档中已经说明了这一点。可以肯定的是,现在代码中存在的问题将使我们成为运行时错误

为了解决这个问题,我们需要创建一个没有重叠的适当的有歧视的联盟

interface BaseArgs {
    title: string
}

interface OnlyTitle extends BaseArgs {
    kind: 'TITLE'
}

interface FuncPagerArgs extends BaseArgs {
    kind: 'PAGER'
    enablePager: true
    limit: number
    count: number
}

type FuncArgs = OnlyTitle | FuncPagerArgs;

function func(args: FuncArgs) {
    if (args.kind === 'PAGER') {
        pager({ limit: args.limit, count: args.count });
    }
}

interface PagerArgs {
    limit: number
    count: number
}

function pager(args: PagerArgs) {

}

func({
    kind: "TITLE",
    enablePager: true
}) // error 

func({
    kind: "TITLE",
    title: 'title'
}) // correct 
我所做的是以
kind
属性的形式,它将允许在适当的成员上不存在任何重叠。这意味着现在您只能使用或一个或另一个变体,类型永远不会重叠

在评论之后编辑 作者在评论中表示,他需要将所有选项组合在一起,但当某项功能启用时,所有与该功能相关的选项都应包含在内。这种结构我们可以通过分组分离选项+加入选项来实现。考虑:

interface Base {
    title: string
}
interface Pager  {
  pager?: {
    limit: number
    count: number
  }  
}

interface Sort {
  sorter?: {
    columns: string[] // example property
  }  
}

type Options = Pager & Sort & Base;

function func(args: Options) {
    if (args.pager) {
        pager({ limit: args.pager.limit, count: args.pager.count });
    }
    if (args.sorter) {
       sorter(args.sorter.columns)
    }
}

func({
  title: 'title',
  pager: {count: 2, limit: 10} // all fields its ok
})


func({
  title: 'title',
  pager: {count: 2} // error limit is missing
})


现在我们可以将
pager
sorter
放在一起,当您有
pager
时,您需要根据需要放置与之相关的所有选项。

这种有区别的联合完全阻止了一次执行多个操作的能力。我的问题是我想有多个功能切换,每个都有自己所需的属性。如果必须使用字符串文字作为判别式,则不能使用多个字符。没有办法使用数组或对象作为判别式吗<代码>功能:{pager:true}或
功能:[“pager”]
这样,另一个arg对象可以是
功能:[“pager”,“sorting”]
等?感谢您的澄清。我更新了我的答案,我想这就是你需要的。那种歧视性的结合完全阻止了一次做多个的能力。我的问题是我想有多个功能切换,每个都有自己所需的属性。如果必须使用字符串文字作为判别式,则不能使用多个字符。没有办法使用数组或对象作为判别式吗<代码>功能:{pager:true}或
功能:[“pager”]
这样,另一个arg对象可以是
功能:[“pager”,“sorting”]
等?感谢您的澄清。我更新了我的答案,我想这就是你需要的。