Typescript 映射类型->;类型,类似于字符串->;通过键盘输入

Typescript 映射类型->;类型,类似于字符串->;通过键盘输入,typescript,Typescript,在TypeScript中,我可以定义以下类型: interface FooNameMapping { Bar: {bar: string}; Baz: {baz: number}; } 然后,我可以在签名中使用密钥和映射类型: function mapped<K extends keyof FooNameMapping>(arg: K): FooNameMapping[K] { return '' as any; } 但是,这仅适用于从字符串参数映射的类

在TypeScript中,我可以定义以下类型:

interface FooNameMapping {
    Bar: {bar: string};
    Baz: {baz: number};
}
然后,我可以在签名中使用密钥和映射类型:

function mapped<K extends keyof FooNameMapping>(arg: K): FooNameMapping[K] {
    return '' as any;
}

但是,这仅适用于从字符串参数映射的类型。是否有任何方法可以对从另一个类型映射的类型执行类似的操作

换句话说,我有以下重载:

interface EnumeratorConstructor {
    new(col: Excel.Actions): Enumerator<Excel.Action>;
    new(col: Excel.AddIns | Excel.AddIns2): Enumerator<Excel.AddIn>;
    new(col: Excel.AllowEditRanges): Enumerator<Excel.AllowEditRange>;
    new(col: Excel.Areas | Excel.Ranges | Excel.Range): Enumerator<Excel.Range>;
    new(col: Excel.Borders): Enumerator<Excel.Border>;
}
接口枚举器构造函数{
新建(列:Excel.Actions):枚举器;
新增(col:Excel.AddIns | Excel.AddIns2):枚举器;
新的(列:Excel.AllowEditRanges):枚举器;
新建(列:Excel.Areas | Excel.Ranges | Excel.Range):枚举器;
新(列:Excel.Borders):枚举器;
}

我是否可以创建一个类型,以某种方式从
Excel.Actions
映射到
Excel.Action
,并在单个重载中使用该类型?

据我所知,目前没有非黑客方法来实现这一点,并使自动推断正常工作。TypeScript目前缺少,这是您需要直接实现的。TypeScript有一个
typeof
操作符,如果它特别适用于任意表达式,将满足您的需要

您现在可以做的是制作如下类型:

interface Example {
    a: {from: string, to: number};
    b: {from: number, to: string};
}
declare function typeMapping<K extends keyof Example>(x: Example[K]['from']): Example[K]['to'];
但这比仅仅使用函数重载要糟糕得多


要做到这一点,最简单的方法是使用扩展作为函数输入的对象的类型,并显式地给它们一个输出类型的幻影属性。例如:

import * as Excel from 'excel'; // guessing at location

// add phantom property
declare module 'excel' {
  interface Actions {
    __outputType: Excel.Action
  }
  interface AddIns {
    __outputType: Excel.AddIn
  }
  interface AddIns2 {
    __outputType: Excel.AddIn
  }
  interface AllowEditRanges {
    __outputType: Excel.AllowEditRange
  }
  // ... etc
}

type Inputs = Excel.Actions | Excel.AddIns | Excel.AddIns2 | Excel.AllowEditRanges // ...

// here's the function now    
declare function constructEnumerator<I extends Inputs>(i: I): Enumerator<I['__outputType']>; 

declare let actions: Excel.Actions;
const ret = constructEnumerator(actions); // returns Enumerator<Excel.Action> as desired
import*作为Excel从“Excel”导入;//猜测位置
//添加幻影属性
声明模块“excel”{
接口动作{
__输出类型:Excel.Action
}
接口插件{
__输出类型:Excel.AddIn
}
接口插件2{
__输出类型:Excel.AddIn
}
接口允许的范围{
__输出类型:Excel.AllowEditRange
}
//…等等
}
输入类型=Excel.Actions | Excel.AddIns | Excel.AddIns2 | Excel.AllowEditRanges/。。。
//下面是函数
声明函数构造函数枚举器(i:i):枚举器;
声明let操作:Excel.actions;
const ret=构造函数枚举器(操作);//根据需要返回枚举数
这一切尽可能地有效,但您可能会发现TypeScript抱怨用于创建任何这些输入类型的对象文本中缺少
\uuuOutputType
,因此您需要处理这一点(例如,
作为Excel.Actions
在文本之后)。值得吗


那么,你有多迫切地需要这个?在TypeScript中出现类型级函数之前和之前,是否可以处理重载或不太特定的类型?或者模块扩充黑客是未来的发展方向?我想这取决于你


无论如何,希望这有帮助;祝你好运

我不确定我是否理解你所说的“以某种方式创建一个将从Excel.Actions映射到Excel.Action的类型”的意思。这种类型的成员会有什么?我想他指的是类似Haskell的类型族,其中,
DesiredType
是从一种类型到另一种类型的“函数”(
DesiredType=…
/type构造函数
DesiredType:->*
)和
DesiredType=Action
DesiredType=AddIn
DesiredType=//error
(或
从不
,或
任何
)等等,就像
mapped
中的
K
是如何以一种迂回的方式从字符串映射到类型的。我非常怀疑,从类型级编程的最深处来看,这样的东西在TS中是否具有等效性。@TitianCernicova Dragomir我的意思是,正如HTNW在评论中所说,我正在寻找指定两者之间的关系然后可以在参数类型和返回类型的函数签名中使用的类型,很像
K extends keyof
使用特定字符串(作为
FooNameMapping
的键)与特定类型(FooNameMapping的类型)之间的关系构建使用给定字符串作为参数并返回相关类型的重载。谢谢您的回答。在这种情况下,这些对象永远不会通过object literal创建,而是始终使用
new ActiveXObject
factory函数或其他此类对象的方法;因此我可以使用phantom属性。但是,我不认为我会使用这个;感觉太“黑”。这可以使用新的in-Typescript 2.8实现吗?是的。您现在可以将列表硬编码为如下内容:
type Enumerator=I extensed Excel.Actions?Excel.Action:I extensed Excel.Addins | Excel.Addins2?Excel.Addin:..
。可能还有一种方法可以使用通用的
类型映射,其中
T
是put类型和
M
是从输入类型到输出类型的映射;不确定这对您有多重要。
let str: string;   
str = typeMapping(123); // error, return value is string|number
str = typeMapping<'b'>(123); // okay, but need to specify 'b'
str = typeMapping<'a'>(123); // error, 1 is not a string
import * as Excel from 'excel'; // guessing at location

// add phantom property
declare module 'excel' {
  interface Actions {
    __outputType: Excel.Action
  }
  interface AddIns {
    __outputType: Excel.AddIn
  }
  interface AddIns2 {
    __outputType: Excel.AddIn
  }
  interface AllowEditRanges {
    __outputType: Excel.AllowEditRange
  }
  // ... etc
}

type Inputs = Excel.Actions | Excel.AddIns | Excel.AddIns2 | Excel.AllowEditRanges // ...

// here's the function now    
declare function constructEnumerator<I extends Inputs>(i: I): Enumerator<I['__outputType']>; 

declare let actions: Excel.Actions;
const ret = constructEnumerator(actions); // returns Enumerator<Excel.Action> as desired