如何处理TypeScript中的“对象可能未定义”错误

时间:2019-01-23 09:44:22

标签: typescript

我有一个函数,其中param可以是字符串或未定义,但是如果未定义,则验证检查会引发错误。任何进一步的代码都可以保证定义了param,但是我现在正与可能未定义的TypeScript强制转换进行斗争。 TypeScript处理此问题的好方法是什么?

import { validatePetFields } from "../models/pets";

interface controllerParams {
   req: {
      petName?: string;
   };
}

export default async ({ req }: controllerParams): Promise<any> => {

   validatePetFields(req, [
      "petName",
   ]); // this function intentionally throws a JS error if petName is undefined

   console.log(req.petName.charAt(0).toUpperCase() + req.petName.slice(1)); // throws TypeScript error: Object is possibly 'undefined'
};

1 个答案:

答案 0 :(得分:0)

您可以使用类型保护,但必须将validate调用包装在if语句中。这基本上告诉编译器,如果该函数返回true,则在if块内,req的类型现在是派生类型,该类型具有所需的所有那些键(作为参数传递)。

类似的东西:

type HasKeys<T, K extends keyof T> = T & { [Key in K]-?: T[Key] };

// function in a function to infer the key types 
// unfortunately it can't infer the type of the req 
// since it needs to be passed in the second function
// you could fix type inference for req by passing it as an argument to both functions
function validatePetFields<T>() {
    return function <K extends keyof T>(obj: T, ...keys: K[]): obj is HasKeys<T, K> {
        for (const key of keys) {
            if (obj[key] === void 0) {
                throw new Error('not valid');
            }
        }
        return true;
    };
}

interface Request {
    petName?: string;
}

export default async (req: Request): Promise<any> => {
    if (validatePetFields<Request>()(req, 'petName')) {
        // no more error since petName is not optional here :)
        console.log(req.petName.charAt(0).toUpperCase() + req.petName.slice(1));
    }
};