TypeScript не может вывести ограниченный тип в универсальном методе? - PullRequest
1 голос
/ 27 мая 2019

Я довольно новичок в TypeScript с сильным фоном в C #.

Интересно, каковы точные причины того, что вывод типов не работает в следующей ситуации в TypeScript, но работает в C #:

TypeScript:

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?

1 Ответ

1 голос
/ 27 мая 2019

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 , объясняя некоторые из этого.

...