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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/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
Typescript 如何专门化受歧视的工会类型?_Typescript - Fatal编程技术网

Typescript 如何专门化受歧视的工会类型?

Typescript 如何专门化受歧视的工会类型?,typescript,Typescript,假设我有两个有区别的联合和第三个类型别名,它是包含这两个联合的联合类型 如何创建一个函数,该函数可以接受两个有区别的联合,但其返回类型取决于传递的值的特定类型 如果传递的值属于First和number的话,Specialize会返回{value:number},如果它属于Second的话,我认为这是可行的,但是它不会返回 type First=“a”|“b”; 键入Second=“c”|“d”; 输入字母=第一个|第二个; 类型Specialize=R首先扩展?{value:number}:nu

假设我有两个有区别的联合和第三个类型别名,它是包含这两个联合的联合类型

如何创建一个函数,该函数可以接受两个有区别的联合,但其返回类型取决于传递的值的特定类型

如果传递的值属于
First
number
的话,
Specialize
会返回
{value:number}
,如果它属于
Second
的话,我认为这是可行的,但是它不会返回

type First=“a”|“b”;
键入Second=“c”|“d”;
输入字母=第一个|第二个;
类型Specialize=R首先扩展?{value:number}:number;
const fun=(字母:M):R=>{
返回字母==“a”|字母==“b”
?{value:1}
: 2;
}
我在这里误解了什么

请注意,我不想删除约束返回类型的
R
。相反,我希望将返回类型约束为传递的参数



这是一个重载作业。通过为缩小的情况提供特定的重载,返回值也将缩小

// Overloads
function fun(letter: First): { value: number };
function fun(letter: Second): number;
// General case
function fun(letter: Letter): { value: number } | number {
    return letter === "a" || letter === "b"
        ? { value: 1 }
        : 2;
}

const x = fun("a")   // x: { value: number }
const y = fun("c")   // y: number
基于泛型的方法无法工作,因为调用方可以决定
R
是什么,并且
R
可以是扩展
专门化的任何类型。这就是错误告诉你的。您无法返回调用方选择的特定子类型


(考虑到TypeScript的结构类型,我不知道创建
Specialize
子类型的具体方法。但是编译器无法证明这是不可能的,而且我相信比我更聪明的人可以想到一个。但是通过使用
extends
,你明确地说调用方可能需要子类型,并且t使得返回
R
不可能。)

主要问题是泛型约束给出的多态性

将函数定义为泛型函数,并使用从另一个类型扩展而来的参数类型,必须确保
return
语句实际返回一个值,该值可赋值为
T
类型及其扩展名(其中
T
是类型参数)

假设您定义了这个类型

type MoreSpecialize<R> = R extends First ? { value: 10 } : 20;
但是,
r
实际上不是
moreespecialize
类型,因为
fun
返回
{value:1}2
,而不是
{value:10}20
。这就是编译器抱怨的原因

解决方案
  • 如果确实不需要扩展,请使用具体类型定义函数
  • const-fun=(字母:字母):Specialize=>{
    返回字母==“a”|字母==“b”
    ?{value:1}
    : 2;
    }
    
  • 强制强制转换返回值[!]。
    这不是最好的方式
  • constfun2=(字母:M):R=>{
    返回(
    字母==“a”|字母==“b”
    ?{value:1}
    : 2
    )as-R;
    }
    
  • @RobNapier的解决方案非常好
  • 希望能有帮助

    type MoreSpecialize<R> = R extends First ? { value: 10 } : 20;
    
    const r: MoreSpecialize<Letter> = fun2<Letter, MoreSpecialize<Letter>>('a');
    
    const fun = (letter: Letter): Specialize<Letter> => {
        return letter === "a" || letter === "b"
            ? { value: 1 }
            : 2;
    }
    
    const fun2 = <M extends Letter, R extends Specialize<M>>(letter: M): R => {
        return (
            letter === "a" || letter === "b"
                ? { value: 1 }
                : 2
        ) as R;
    }