typescript 使用as的更安全替代品

9avjhtql  于 2023-03-13  发布在  TypeScript
关注(0)|答案(2)|浏览(268)

我正在编写TypeScript代码,在某些时候我需要获取HTTP调用的输出(基本上是一个JSON字符串)并将其转换为类型化对象。我使用as子句来完成这项工作,如下所示:

interface MyInterface {
    idUser: string;
    idProducts: string[];
}

const str: string = "{ \"idUser\": \"johndoe\", \"shadowKey\": \"myValue\" }";

const myObject = JSON.parse(str) as MyInterface;

console.log(myObject);

这样就行了,console.log指令将打印:

{
  "idUser": "johndoe",
  "shadowKey": "myValue"
}

我完全理解其基本原理,但我希望有一个更安全的方法。如果没有提供idProducts字段,将引发错误,并在打印时隐藏shadowKey
在TypeScript中实现这一点的最佳/最简单方法是什么?

gzszwxb4

gzszwxb41#

这可以通过TS类型 predicate (以前称为user-defined type guards)来实现。
为此,您需要定义一个返回类型 predicate 的函数,该类型 predicate 检查obj是否具有所需的元素。

interface MyInterface {
    idUser: string;
    idProducts: string[];
}

function isMyInterface(obj: Object): obj is MyInterface {
  return ("idUser" in obj && typeof obj.idUser === "string")   //obj.idUser exists and is a string
    && ("idProducts" in obj && Array.isArray(obj.idProducts)); //obj.idProducts exists and is an Array
}

const str: string = "{ \"idUser\": \"johndoe\", \"shadowKey\": \"myValue\" }";
const myObject: MyInterface = JSON.parse(str) as MyInterface;
if(isMyInterface(myObject)){ // will fail in this example
  console.log("myObject is MyInterface");
} else {
  console.log("myObject is not MyInterface");
}

这几乎是一个js解决方案,除了返回类型,我们可以只返回一个boolean结果(实际上这是js要处理的结果),但是有了这个设置,ts将能够解释结果,并能够给予你编译时的错误/问题。

if(isMyInterface(myObject)){
  console.log(myObject.idProducts); // works
} else {
  console.log(myObject.idProducts); // Error: Property 'idProducts' does not exist on type 'never'.
}
5vf7fwbs

5vf7fwbs2#

我建议使用Zod来验证对象。
示例对象:

const ZodResult = z.object({
  idUser: z.string(),
  idProducts: z.array(z.string()),
});

推断将其用作类型:

type Result = z.infer<typeof ZodResult>;

解析对象,

const parsed = JSON.parse(yourStringObject);
const result = ZodResult.safeParse(parsed);
if (!result.success) {
  // handle error then return
  result.error;
} else {
  // do something with data
  result.data; // data has type Result
}

相关问题