【问题标题】:TypeScript cannot infer constrained type in generic method?TypeScript 不能在泛型方法中推断受约束的类型?
【发布时间】:2019-10-13 00:57:48
【问题描述】:

我是 TypeScript 的新手,具有强大的 C# 背景。

我想知道类型推断在 TypeScript 中的以下情况下似乎不起作用但在 C# 中起作用的确切原因是什么:

打字稿:

interface IResult { }

interface IRequest<TResult extends IResult> { }

interface ISomeResult extends IResult {
    prop: string;
}

interface ISomeRequest extends IRequest<ISomeResult> { }

 function Process<TResult extends IResult>(request: IRequest<TResult>): TResult {
    throw "Not implemented";
}

let request: ISomeRequest = {};
let result = Process(request);
// Error: Property 'prop' does not exist on type '{}'.
console.log(result.prop);

C#

interface IResult { }

interface IRequest<TResult> where TResult : IResult { }

interface ISomeResult : IResult
{
    string Prop { get; set; }
}

interface ISomeRequest : IRequest<ISomeResult> { }

static TResult Process<TResult>(IRequest<TResult> request) where TResult : IResult
{
    throw new NotImplementedException();
}

static void Main()
{
    ISomeRequest request = default;
    var result = Process(request);
    // OK
    Console.WriteLine(result.Prop);
}

这是 TS 编译器的类型推断算法的问题(可能还没有?)还是有一些我遗漏的根本原因使这在 TS 中变得不可能?

【问题讨论】:

    标签: typescript type-inference


    【解决方案1】:

    Typescript 有一个结构化类型系统(如果来自 C#,这可能看起来有点奇怪,我知道我遇到了同样的问题?)。这意味着如果您有一个未使用的类型参数,编译器将忽略它,因为它与类型兼容性无关。将任何使用TResult 的成员添加到IRequest,它就会按您的预期工作:

    interface IResult { }
    
    interface IRequest<TResult extends IResult> { 
        _r?: undefined | TResult
    }
    
    interface ISomeResult extends IResult {
        prop: string;
    }
    
    interface ISomeRequest extends IRequest<ISomeResult> { }
    
    function Process<TResult extends IResult>(request: IRequest<TResult>): TResult {
        throw "Not implemented";
    }
    
    let request: ISomeRequest = { };
    let result = Process(request);
    console.log(result.prop);
    

    FAQ 对此进行了一些解释。

    【讨论】:

    • 哇,你的速度非常快,谢谢!这一切都清楚了。然而,解决方法似乎有点 hacky,FAQ 说“一般来说,你永远不应该有未使用的类型参数。该类型将具有意外的兼容性(如此处所示)并且也无法在函数调用中进行适当的泛型类型推断。 "建议我最好不要走这条路。
    • @AdamSimon 由你决定,添加成员确实有效,我有时会使用它来满足类型系统。如果您可以在请求中找到对结果有意义的用途,那将是理想的选择.. 可能是可选的转换函数或其他东西.. 可能会以有意义的方式使用。
    • 实际上这个解决方案只是为了表达请求和结果类型之间的关系而不是简单的命名约定。当然,作为一个很好的副作用,它允许我编写更少的代码,因为我不需要在调用 Process 时输入结果类型。所以毕竟使用这个无害的技巧是可以的。
    猜你喜欢
    • 2020-10-10
    • 2022-11-23
    • 1970-01-01
    • 2021-06-23
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多