2015-11-03 20 views
1

我想写一个给定数组的函数,从中删除重复的元素。我希望这个函数至少适用于数字和字符串。我的尝试是:删除TypeScript中重复项的函数类型

function removeDuplicates<T>(xs: T[]): T[] 
{ 
    var res: T[] = []; 
    var seen = {}; 
    for (var i = 0; i < xs.length; i++) { 
     var x = xs[i]; 
     if (!(x in seen)) { 
      seen[x] = null; 
      res.push(xs[i]); 
     } 
    } 
    return res; 
} 

哪个是有效的Javascript删除元素(剥离类型后)。然而,在打字稿,我上in线的错误说:

的左手侧的“IN”表达的类型必须是“任何”,“串”的,“数”,或者'符号'。

我试过T extends string | number,但那不行。我想过T is string | number,但我找不到任何TypeScript语法。如何在类型中捕获此属性?

+2

TS在这里适当地给你一个红色的标志,因为您的实现我想可能会出错。你不能有一个对象作为另一个对象的关键。如果你这样做,它只会将对象转换为它的字符串表示[object Object]。所以你的通用逻辑在这里不起作用T是一个对象,我的意思是它的功能本身将会中断。如果你想让TS开心,你可以做var x:any = xs [i];但那不会解决目的。 – PSL

回答

3

一种解决方案是使用显式类型注解any

function removeDuplicates<T>(xs: T[]): T[] 
{ 
    var res: T[] = []; 
    var seen = {}; 
    for (var i = 0; i < xs.length; i++) { 
     var x:any = xs[i]; 
     if (!(x in seen)) { 
      seen[x] = null; 
      res.push(xs[i]); 
     } 
    } 
    return res; 
} 

我还建议明确应用string|number约束:

type ValidKey = string|number; 
function removeDuplicates<T extends ValidKey>(xs: T[]): T[] 
{ 
    var res: T[] = []; 
    var seen = {}; 
    for (var i = 0; i < xs.length; i++) { 
     var x:ValidKey = xs[i]; 
     if (!(x in seen)) { 
      seen[x] = null; 
      res.push(xs[i]); 
     } 
    } 
    return res; 
} 

removeDuplicates(['a','b','a']) // okay 
removeDuplicates([1,2]) // okay 
removeDuplicates([{a:1},{a:2}]) // Not cool 
+0

有没有一种方法可以用Typescript指定'T'的约束? – PSL

+1

@PSL在更新中完成 – basarat

+1

太棒了...我从你的答案中学到了很多东西。谢谢+1! :) – PSL