如何使用属性缩小类型

时间:2019-02-22 05:49:15

标签: typescript

在这种情况下是否可以定义getInterface,以便res具有number类型?

为了澄清:我不是在尝试编写这些方法,而是在一个环境中存在一种方法,该方法根据parameters.type返回不同​​的对象,而我正在尝试寻找一种键入它们的方法

interface A {
  tag: 'a'
  do_one: () => number;
}
interface B {
  tag: 'b'
  do_one: () => string;
}
type Interface = A | B
let one = getInterface({ type: 'a' })
let res = one.do_one()

5 个答案:

答案 0 :(得分:1)

虽然您的问题还不是100%清楚,但在我读给您的内容时,getInterface是哪种类型,并根据类型返回适当的值。

您可以使用重载或条件类型来做到这一点:

有重载:

type Interface = A | B

function getInterface(v: { type: 'a' }): A
function getInterface(v: { type: 'b'}): B 
function getInterface(v: { type: 'b'} | { type: 'a'}): A | B {
    return null!
}
let one = getInterface({ type: 'a' })
let res = one.do_one()

具有条件类型

interface A {
    tag: 'a'
    do_one: () => number;
}
interface B {
    tag: 'b'
    do_one: () => string;
}
type Interface = A | B

type GetJustTypes = Interface extends infer I ? I extends { tag: infer U } ? { tag: U } : never : never
function getInterface<T extends GetJustTypes>(v: T): Extract<Interface, T>
function getInterface(v: { tag: 'b' } | { tag: 'a' }): A | B {
    return null!
}
let one = getInterface({ tag: 'a' })
let res = one.do_one()

答案 1 :(得分:1)

declare function getInterface(arg: { type: 'a' }): A;
declare function getInterface(arg: { type: 'b' }): B;

let one = getInterface({ type: 'a'} )
let res = one.do_one()  // res is a number

答案 2 :(得分:1)

谢谢您的帮助!我承认我的问题有点混乱,我肯定应该更清楚一些。

无论如何,我设法输入正确的字-

type FilterTag<T, U> = T extends { tag: U } ? T : never
type Interface<T> = FilterTag<A | B, T>
declare function getInterface<T extends string>(params: { type: T }): Interface<T>

这意味着getInterface({ type 'X' })将始终返回正确的界面,并且每当需要更改时,只有一种联合类型可供编辑

答案 3 :(得分:0)

必须基本处理do_one()函数

getInterface(<someparam>):number{
   do_one():number{
      return 4;
   }
}
let res:number = one.do_one();

答案 4 :(得分:0)

我们需要更清楚地了解键入内容,存在键入内容是为了避免在编译期间出现错误。编译后,最终结果将为纯javascript

对于您的问题,只能使用 | 条件添加键入,这些条件仅在编译过程中进行检查。

动态打字是一个有待解决的神话。

但是有一种方法instance-of可以使用。