代码之家  ›  专栏  ›  技术社区  ›  laptou

不能将空值分配给类型

  •  0
  • laptou  · 技术社区  · 5 年前

    在我的typescript项目中,我创建了一个自定义类(灵感来自rust's Result<T, E> (顺便说一句)看起来是这样的:

    export class Result<T, E extends Error = Error>
    {
        public errors: E[] = [];
        public result: T | null = null;
    
        public static ok<T, E extends Error>(result: T): Result<T, E>
        {
            return new Result(result, [] as E[]);
        }
    
        public static err<T, E extends Error>(...errors: E[]): Result<T, E>
        {
            return new Result<T, E>(null as unknown as T, errors);
        }
    
        public static apiErr<T>(...errors: ApiErrorKind[]): Result<T, ApiError>
        {
            return new Result<T, ApiError>(null as unknown as T, errors.map(e => new ApiError(e)));
        }
    
        private constructor(result: T | null, errors: E[])
        {
            this.result = result;
            this.errors = errors;
        }
    
        public and<T2, E2 extends Error = E>(f: (x: T) => Result<T2, E2>): Result<T2, E | E2>
        {
            if (this.isErr)
                return Result.err(...this.errors);
    
            let errors: (E | E2)[] = this.errors;
    
            try
            {
                return f(this.result as T);
            }
            catch (e)
            {
                errors.push(e as E2);
            }
    
            return Result.err(...errors);
        }
    
        // irrelevant methods omitted for brevity
    
        public then<T2, E2 extends Error = E>(f: (x: T | null) => T2): Result<T2, E | E2>
        {
            if (this.isErr)
                return Result.err(...this.errors);
    
            let errors: (E | E2)[] = this.errors;
    
            try
            {
                return Result.ok(f(this.result));
            }
            catch (e)
            {
                errors.push(e as E2);
            }
    
            return Result.err(...errors);
        }
    }
    

    然而,每当我尝试使用它时,我总是会得到关于空值转换的神秘错误,尽管没有任何错误 null 在望:

    export async function createUser(input: UserInput, organization: string): Promise<Result<User, ApiError>>
    {
        const validation = validateUser(input); // returns Result<boolean, ApiError>
    
        if (validation.isErr)
            return Result.err<User, ApiError>(... validation.errors); // Error on this line
    }
    

    TS23 22 类型“user null”不能分配给类型“result”。类型“null”不能分配给类型“result”。

    为什么会这样?

    0 回复  |  直到 5 年前
        1
  •  1
  •   laptou    5 年前

    这个问题是由我放了一个事实引起的。 then 我的方法 Result<T, E> 类型。当我试图从 async 方法,因为typescript一直假设 结果<t,e> 是伪的 Promise 试图通过打电话打开它 .then() .

    对于这种情况,typescript通常有一个更清楚的错误:

    TS1058 异步函数的返回类型必须是有效的承诺,或者不能包含可调用的“then”成员。

    但一旦方法接受函数作为参数,它就会变得更加混乱,因为这就是 许诺 的方法签名看起来像,而且它与所涉及的泛型更加混淆。

        2
  •  0
  •   Mohammad Yasir Arafat    5 年前

    可以在TSCONS.JSON的编译器选项中设置“StrutUnLultCuffs:false”。

    有关详细信息,请参见 this 回答,以及 this 链接。