高阶函数中的泛型类型

时间:2017-08-01 15:00:35

标签: typescript

我想使用泛型类型作为高阶函数的内部函数中的参数。但是,当我这样做时,外部函数上的参数会丢失它们的类型(变为any)。

以下是我尝试做的一个例子。我希望第2行会出错。

type TestFunc = <T>(outerArg: string) => (innerArg: T) => number
const test: TestFunc = <T>(outerArg) => (innerArg: T) => innerArg ? outerArg * 3 : 0 // no error because `outerArg` is `any` (unexpected)

如果innerArg不是通用的,我会收到我期望的错误:

type TestFunc = (outerArg: string) => (innerArg: boolean) => number
const test: TestFunc = (outerArg) => (innerArg: boolean) => innerArg ? outerArg * 3 : 0 // error because `outerArg` is `string` (expected)

问题

在第一个示例的第2行,outerArg的类型为any。在第二个示例的第2行,outerArg的类型为string。他们为什么不同?

更多详情

我的目标是在评估外部函数时允许指定T。例如:

type TestFunc = <T>(outerArg: string) => (innerArg: T) => number
const test: TestFunc = (outerArg) => (innerArg) => innerArg ? outerArg.length * 3 : 0 
const test2: TestFunc = <T>(outerArg) => (innerArg: T) => innerArg ? outerArg * 3 : 0 // want error


const fourBool = test<boolean>('str')
console.log(fourBool(true))
console.log(fourBool(1)) // want error

const fourNum = test<number>('str')
console.log(fourNum(true)) // want error
console.log(fourNum(1))

此处位于typescript playground

2 个答案:

答案 0 :(得分:2)

您有两个功能:

1)具有返回数字的泛型类型的函数

2)和一个带数字并返回通用的函数。

正如您在评论中提到的那样,您使用带有类型参数的箭头函数,但这对两个函数都不起作用。您可以将内部函数声明为泛型函数,并将外部函数声明为类型参数:

type InnerFunc<T> = (inner: T) => number;
type TestFunc = <T>(outer: number) => InnerFunc<T>;

const test: TestFunc = <T>(outerArg: number) => (innerArg: T) => innerArg ? outerArg * 3 : 0;

const fourBool = test<boolean>(4);
fourBool(true); // OK
fourBool(1);    // error

答案 1 :(得分:1)

看起来这可能是编译器或设计中的错误。

但是,这可能适用于将通用类型附加到使用泛型类型的函数的解决方法。

type TestFunc = (arg1: string) => <T>(a: T) => number
type Number1 = (a: number) => number
const test: TestFunc = (arg1) => (a) => a ? (arg1 ? 1 : 2) : 0
const num1: Number1 = test("blah")
// OR
const newNum1 = <Number1>test("bleh")

好的,这就是你想要做到你想做的事情的方式:

arg1

如果您像以前一样放置type TestFunc1 = <T>(arg1: string) => (a: T) => number const test1: TestFunc1 = (arg1: string) => a => a ? (arg1 ? 1 : 2) : 0 const newNum2 = test1<number>("bluh") ,上面会给您错误,它会为您提供您之前想要的通用表单。你会注意到你是否定义了&#34;子类型&#34;错误,它也会产生编译错误。

为了完整起见,这是一个更简单的解决方案(几乎是cdbajorin在他的解决方案中所做的):

-- Defining your string
DECLARE @string varchar(max)
SET @string = 'Consolidation CompletedThe Scenario is LDP; the Year is 2018; the Start Period is July; the End Period is June; the Entity is TOT_NEWS.'


;with pos as (
SELECT 
 @string as String
,CHARINDEX(';', @string, 1) as Pos_1
,CHARINDEX(';', @string, CHARINDEX(';', @string, 1)+1) as Pos_2
,CHARINDEX(';', @string, CHARINDEX(';', @string, CHARINDEX(';', @string, 1)+1)+1) as Pos_3
,CHARINDEX(';', @string, CHARINDEX(';', @string, CHARINDEX(';', @string, CHARINDEX(';', @string, 1)+1)+1)+1) as Pos_4
) , txt as (
select 
 String
,substring(String, 1,Pos_1-1) as String_1
,substring(String,Pos_1+1,Pos_2-Pos_1-1) as String_2
,substring(String,Pos_2+1,Pos_3-Pos_2-1) as String_3
,substring(String,Pos_3+1,Pos_4-Pos_3-1) as String_4
,substring(String,Pos_4+1,LEN(String)-Pos_4-1) as String_5
from pos
) 
SELECT
 string
,substring(String_1,len(String_1)-charindex(' ',reverse(String_1),1)+1,charindex(' ',reverse(String_1))) as Result_1
,substring(String_2,len(String_2)-charindex(' ',reverse(String_2),1)+1,charindex(' ',reverse(String_2))) as Result_2
,substring(String_3,len(String_3)-charindex(' ',reverse(String_3),1)+1,charindex(' ',reverse(String_3))) as Result_3
,substring(String_4,len(String_4)-charindex(' ',reverse(String_4),1)+1,charindex(' ',reverse(String_4))) as Result_4
,substring(String_5,len(String_5)-charindex(' ',reverse(String_5),1)+1,charindex(' ',reverse(String_5))) as Result_5
from txt