Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.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
Generics 转换TypeScript中的泛型接口类型_Generics_Typescript - Fatal编程技术网

Generics 转换TypeScript中的泛型接口类型

Generics 转换TypeScript中的泛型接口类型,generics,typescript,Generics,Typescript,我试图弄清楚如何创建一个函数,该函数接受一个泛型类型,它是一个具有键和值的对象,并返回一个具有相同接口的类型,但修改该对象的值。用通俗易懂的英语解释有点困难,所以这里有一个例子: 这是一个虚构的类,它具有泛型类型并封装了一个值 class Wrap<A> { constructor(public value: A) {} } 我试图找出如何为这些函数创建类型签名,同时尽可能维护类型安全性。例如,如果输入类型是一个接口,我还想输出一个接口: interface Ex1Inpu

我试图弄清楚如何创建一个函数,该函数接受一个泛型类型,它是一个具有键和值的对象,并返回一个具有相同接口的类型,但修改该对象的值。用通俗易懂的英语解释有点困难,所以这里有一个例子:

这是一个虚构的类,它具有泛型类型并封装了一个值

class Wrap<A> {
    constructor(public value: A) {}
}
我试图找出如何为这些函数创建类型签名,同时尽可能维护类型安全性。例如,如果输入类型是一个接口,我还想输出一个接口:

interface Ex1Input {
    a: number
    b: string
}

interface Ex1Output {
    a: Wrap<number>
    b: Wrap<string>
}

interface Ex2Input {
    a: number
    b: Wrap<string>
}

interface Ex2Output {
    a: Wrap<number>
    b: Wrap<string>
}
我试过几种不同的方法。。。这可能是我所做的最接近的一次,但我觉得它离我想要的工作还有很长的路要走

interface WrapInput {
    [key: string]: any
}

interface WrapOutput extends WrapInput {
    [key: string]: Wrap<WrapInput[keyof WrapInput]>
}

function wrap<T extends WrapInput>(obj: T): WrapOutput {
    const result: WrapOutput = {}
    Object.keys(obj).forEach(key => {
        if (obj[key] instanceof Wrap) {
            result[key] = obj[key]
        } else {
            result[key] = new Wrap(obj[key])
        }
    })
    return result
}
接口封装输出{
[键:字符串]:任何
}
接口WrapOutput扩展WrapInput{
[键:字符串]:换行
}
函数换行(obj:T):换行输出{
常量结果:WrapOutput={}
Object.keys(obj.forEach)(key=>{
if(obj[key]包裹实例){
结果[键]=对象[键]
}否则{
结果[键]=新换行(obj[键])
}
})
返回结果
}

有什么想法吗?这可能吗?只是重申一下——我对一个尽可能类型安全的解决方案感兴趣。因此,如果我将
wrap
Ex1Input
一起使用,编辑器中的自动完成功能应该会显示输出上只有两个属性及其特定类型。

您可以尝试以下操作吗

function wrap<T>(obj: T): T {
    const result: any = {}
    Object.keys(obj).forEach(key => {
        if ((obj as any)[key] instanceof Wrap) {
            result[key] = (obj as any)[key]
        } else {
            result[key] = new Wrap((obj as any)[key])
        }
    })
    return result
}


const data = { someData: 1 }
var test = wrap(data)
test.someData //  the autocomplete in my editor shows someData with intellisense
函数换行(obj:T):T{
常量结果:any={}
Object.keys(obj.forEach)(key=>{
如果((对象如有)[key]包裹实例){
结果[键]=(obj如有)[键]
}否则{
结果[键]=新换行((obj作为任何对象)[键])
}
})
返回结果
}
const data={someData:1}
var测试=换行(数据)
test.someData//“我的编辑器”中的“自动完成”显示带有intellisense的someData
您可以使用(
在下面的示例中可以是Wrapped
Wrapped

类换行{
构造函数(公共值:值){}
}
类型可能被包装={
[K in keyof T]:T[K]| Wrap;
};
类型包装={
[K in keyof T]:包裹;
};
函数包装(arg:maybewapped):包装{
//您在这里的实现
}
函数展开(arg:maybewapped):T{
//您在这里的实现
}
声明常量输入:{
a:包裹
b:日期
};
const wrapped=wrapp(输入);
wrapped.a.value.length;//包裹。a被推断为包裹
wrapped.b.value.getTime();//包裹。b被推断为包裹
常量展开=展开(输入);
未包装的a.长度;//未包装。a被推断为字符串
unwrapped.b.getTime();//未包装。b被推断为日期

感谢您在SO中的回答。请描述你的答案,解释你在做什么。想象一下坐在提问者旁边,试图解释如何解决问题,而不是给出答案。
interface WrapInput {
    [key: string]: any
}

interface WrapOutput extends WrapInput {
    [key: string]: Wrap<WrapInput[keyof WrapInput]>
}

function wrap<T extends WrapInput>(obj: T): WrapOutput {
    const result: WrapOutput = {}
    Object.keys(obj).forEach(key => {
        if (obj[key] instanceof Wrap) {
            result[key] = obj[key]
        } else {
            result[key] = new Wrap(obj[key])
        }
    })
    return result
}
function wrap<T>(obj: T): T {
    const result: any = {}
    Object.keys(obj).forEach(key => {
        if ((obj as any)[key] instanceof Wrap) {
            result[key] = (obj as any)[key]
        } else {
            result[key] = new Wrap((obj as any)[key])
        }
    })
    return result
}


const data = { someData: 1 }
var test = wrap(data)
test.someData //  the autocomplete in my editor shows someData with intellisense
class Wrap<Value> {
  constructor(public value: Value) {}
}

type MaybeWrapped<T> = {
  [K in keyof T]: T[K] | Wrap<T[K]>;
};

type Wrapped<T> = {
  [K in keyof T]: Wrap<T[K]>;
};

function wrap<T>(arg: MaybeWrapped<T>): Wrapped<T> {
  // your implementation here
}

function unwrap<T>(arg: MaybeWrapped<T>): T {
  // your implementation here
}

declare const input: {
  a: Wrap<string>
  b: Date
};

const wrapped = wrap(input);
wrapped.a.value.length; // wrapped.a is infered as Wrap<string>
wrapped.b.value.getTime(); // wrapped.b is infered as Wrap<Date>

const unwrapped = unwrap(input);
unwrapped.a.length; // unwrapped.a is infered as string
unwrapped.b.getTime(); // unwrapped.b is infered as Date