Joy*_*nda 5 serialization discriminated-union typescript
鉴于打字稿代码片段:
class Excel {
Password: string;
Sheet: number;
}
class Csv {
Separator: string;
Encoding: string;
}
type FileType = Excel | Csv
let input = '{"Separator": ",", "Encoding": "UTF-8"}';
let output = Object.setPrototypeOf(JSON.parse(input), FileType.prototype) // error!
Run Code Online (Sandbox Code Playgroud)
在 TypeScript/Javascript 中,要从 JSON 反序列化,可以使用Object.setPrototypeOf(),其第二个参数需要“原型”。对于类,例如Excel,一个人可以做Excel.prototype。但是使用上面的 Discriminated Union,我遇到了一个错误:
error TS2693: 'FileType' only refers to a type, but is being used as a value here.
Run Code Online (Sandbox Code Playgroud)
Excel/Csv和 JSON 字符串序列化它们中的任何一个;取回正确的实例化对象),无论使用什么技巧、类、类继承、接口、有区别的联合或不...?let json = JSON.parse(input);
let output: FileType | null = null;
if (json["Separator"]) {
console.log("It's csv");
output = Object.setPrototypeOf(json, Csv.prototype)
} else if (json["Password"]) {
console.log("It's excel");
output = Object.setPrototypeOf(json, Excel.prototype)
} else {
console.log("Error");
}
Run Code Online (Sandbox Code Playgroud)
很容易认识到这种方法很麻烦(if else很多),尤其是在添加新类时。此外,开发人员必须选择一个唯一的字段来检查每个类......
在您的示例中,FileType不是一个类,它只是一个编译时联合类型。不会为 生成运行时代码FileType,因此虽然类型检查器理解其含义,但在运行时没有FileType定义可从中检索protoptype属性的对象。
我不清楚为什么您需要首先设置反序列化对象的原型。为什么不直接这样声明:
let output = JSON.parse(input) as FileType;
if (IsExcel(output)) { /* do stuff with output.Password & .Sheet */ }
else { /* do stuff with output.Seperator and .Encoding }
Run Code Online (Sandbox Code Playgroud)
IsExcel() 是判断反序列化的对象是否是 Excel 类型,应该写成User-Defined Type Guard,但可能是这样的
function IsExcel(f: FileType): f is Excel { . . . }
Run Code Online (Sandbox Code Playgroud)
IsExcel 返回一个布尔值,但通过以这种方式编写返回类型,TypeScript 可以理解它正在读取可判别联合的判别器。您可以以任何您想要的方式进行检查,例如通过检查是否(<any>f).Sheet已定义。
| 归档时间: |
|
| 查看次数: |
1248 次 |
| 最近记录: |