Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.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
Typescript 当与另一个类型化函数一起传递给泛型函数时,字符串缩小为字符串文字类型_Typescript_Typescript Generics - Fatal编程技术网

Typescript 当与另一个类型化函数一起传递给泛型函数时,字符串缩小为字符串文字类型

Typescript 当与另一个类型化函数一起传递给泛型函数时,字符串缩小为字符串文字类型,typescript,typescript-generics,Typescript,Typescript Generics,在下面的示例中,我有一个函数将泛型类型V作为参数,另外一个函数也将V作为参数 当我用一个字符串调用该函数时,以及一个从原始函数的签名推断其参数类型的匿名函数,我会得到一个我所期望的结果:string 但是,当我使用符合签名的单独声明的函数调用它时,字符串参数的类型被缩小为字符串文本 type Placeholder<V> = (value: V) => void; const myTestFunction = <V extends any>( value:

在下面的示例中,我有一个函数将泛型类型
V
作为参数,另外一个函数也将
V
作为参数

当我用一个字符串调用该函数时,以及一个从原始函数的签名推断其参数类型的匿名函数,我会得到一个我所期望的结果:
string

但是,当我使用符合签名的单独声明的函数调用它时,字符串参数的类型被缩小为字符串文本

type Placeholder<V> = (value: V) => void;

const myTestFunction = <V extends any>(
    value: V,
    placeholder: Placeholder<V>
) => {
    return value;
}

const aTypedFunction = (value: string) => { return };

// "isLiteralType"
const typedResult       = myTestFunction("isLiteralType", aTypedFunction);

// "string"
const inferredResult    = myTestFunction("isStringType", (value) => { return });
类型占位符=(值:V)=>void;
常量myTestFunction=(
值:V,
占位符:占位符
) => {
返回值;
}
constAtypedFunction=(值:string)=>{return};
//“isLiteralType”
const typedResult=myTestFunction(“isLiteralType”,aTypedFunction);
//“字符串”
const inferredResult=myTestFunction(“isStringType”,(value)=>{return});

这似乎是由于在
aTypedFunction
中显式键入
参数所致,因为在匿名函数中显式键入参数也会产生字符串文本结果。然而,我不知道为什么会出现这种情况


为什么会发生这种类型缩小,我如何更改
myTestFunction
aTypedFunction
,以便前者将后者作为参数接受,而不缩小类型?

类型参数通常是从一个参数推断出来的;对于您的函数,
V
将从参数
value:V
中推断出来,因为它的类型是原始类型参数,因此给定函数的调用,类型
V
可以非常容易地推断出来-只需查看调用中第一个参数的类型,并将其用于
V
。这就是这里发生的事情,这就是为什么
V
在调用
myTestFunction(“isLiteralType”,aTypedFunction)
时被推断为
“isLiteralType”

当您直接传递键入的箭头函数时,同样适用。也就是说,我实际上不知道为什么使用未键入的箭头函数会得到不同的结果。我和你一样对此感到好奇

幸运的是,我们不需要弄清楚为什么第二个示例的行为会有所不同:如果我们希望从
占位符
而不是
推断类型参数,那么我们就知道类型参数通常会从更容易推断的参数中推断出来,将其设置为
占位符:P
,而不是
值:V
。我在下面编写了一个解决方案,它从
P
派生
值的类型,而不是从
V
派生
占位符的类型

type Placeholder<V> = (value: V) => void;
type PlaceholderComponent<P extends Placeholder<any>> = P extends Placeholder<infer V> ? V : never

const myTestFunction = <P extends Placeholder<any>>(
    value: PlaceholderComponent<P>,
    placeholder: P
) => {
    return value;
}

const aTypedFunction = (value: string) => { return };

// string
const typedResult       = myTestFunction("isLiteralType", aTypedFunction);
类型占位符=(值:V)=>void;

输入Placeholder Component谢谢,这很好,尽管我刚刚意识到我的问题比我想象的要简单得多,并且通过回答的第一部分得到了解决。我习惯于字符串在由
const
定义时仅为文本,或者作为某个对象上的属性,而不是作为参数内联传递-问题在于测试用例,而不是我真正的代码。我确实需要传递函数,以便能够从
推断出它们的参数类型,因此我不认为我可以使用此方法,但我一定会在将来记住此策略。