Typescript只读对象文本

Typescript只读对象文本,typescript,Typescript,我有一个复杂的数据模型,我需要在其中定义40-50个单例“元数据”对象,这些对象: 使用歧视工会 有一些规则字段,但也有一个字典,其中可以包含任意数量的对象属于一个有区别的联合 我希望能够保留为对象文本创建的隐式类型,这样我就可以使用intellisense以类型安全的方式操作这些40-50个对象 以下是使用以下形状的示例: interface Square{ 种类:“方形”; 大小:数量; } 界面矩形{ 种类:“长方形”; 宽度:数字; 高度:数字; } 界面圈{ 种类:“圆圈”; 半径

我有一个复杂的数据模型,我需要在其中定义40-50个单例“元数据”对象,这些对象:

  • 使用歧视工会
  • 有一些规则字段,但也有一个字典,其中可以包含任意数量的对象属于一个有区别的联合
我希望能够保留为对象文本创建的隐式类型,这样我就可以使用intellisense以类型安全的方式操作这些40-50个对象

以下是使用以下形状的示例:

interface Square{
种类:“方形”;
大小:数量;
}
界面矩形{
种类:“长方形”;
宽度:数字;
高度:数字;
}
界面圈{
种类:“圆圈”;
半径:数字;
}
类型形状=方形|矩形|圆形;
类型Shapes={[x:string]:Shape};
接口画布{
名称:字符串;
大小:数量;
//等
}
界面绘图扩展画布{
形状:形状;
}
//编译drawingExplicitType.shapes,但不提供智能感知,因为它是一个字典
let drawingExplicitType:绘图={
名称:'myDrawing',
尺码:100,
形状:{
c:{种类:“圆”,半径:1},
r:{种类:“矩形”,宽度:1,高度:1},
}
};
//编译drawingImplicitType.shapes并为我提供智能感知
让drawingImplicitType={
名称:'myDrawing',
尺码:100,
形状:{
c:{种类:“圆”,半径:1},
r:{种类:“矩形”,宽度:1,高度:1},
}
};
//将有许多像drawingImplicitType(大约40-50)这样的对象,我希望以类型安全的方式操作它们
//这些形状也有子形状,所以它是一个树状的数据模型
//我仍然希望能够将所有“drawing*”对象放入图形数组中
//错误!!!未编译:类型“string”不可分配给类型“circle”。
let drawing:drawing=drawingImplicitType;
//##变通办法##########################################
类Drawing2实现画布{
名称:字符串;
大小:数量;
形状:形状;
fromObjLiteral(
obj:T&{shapes:{readonly[x in keyof T['shapes']]:Shape}}):绘图2
{
分配(本,obj);
归还这个;
}
}
//编译drawingImplicitType2.shapes并为我提供智能感知
让drawingImplicitType2=new(类{
名称='myDrawing';
尺寸=100;
形状=新(类){
c=新的(类{readonly kind=“circle”;radius=1})();
r=new(类{readonly kind=“rectangle”;宽度=1;高度=1})();
})();
})();
让drawing2:drawing2=新的drawing2().fromObjLiteral(drawingImplicitType2);
let数组:Drawing2[]=[Drawing2];
//该解决方案编译后仍然允许我制作Drawing2数组
//但我必须创建新对象,与以下对象相比,语法非常难看:
//让drawingImplicitType2=readonly{…obj literal here…}
编辑2018-05-25

正如所指出的,类型断言使用起来更简单,但是我们需要在所有子对象上使用它们,以获得强类型安全性。这对于递归树型数据模型来说可能有点烦人,
Shape
s可以包含其他
Shape
s,但我认为它比
new(class{…})(

//类型断言可以编译,但允许我产生各种错误:
让drawingTypeAssertion={
名称:'myDrawing',
尺码:100,
不存在字段:123,
形状:{
c:{种类:“圆”,半径:1},
r:{种类:“矩形”,宽度:1,高度:1},
}
};
让drawingTA:Drawing=drawingImplicitType为Drawing;
//#####################################################################
//解决方法2:深层类型断言
//#####################################################################
让drawingDeepTypeAssertion={
名称:'myDrawing',
尺码:100,
不存在字段:123,
形状:{
c:{种类:“圆”,半径:1}作为形状,
r:{种类:“矩形”,宽度:1,高度:1}作为形状,
}
};
让drawingDTA:Drawing=drawingImplicitType为Drawing;
let array2:Drawing[]=[drawingDTA];
//此解决方案编译后仍允许我制作Drawing2数组
//不需要创建额外的对象,而且语法比new(class{…})()好一点
完2018-05-25

变通方法2的一个很大的缺点是,只要执行
as Shape
,就会丢失隐式类型并转到vscode中的定义

据我所知,问题来自这样一个事实,即对象文本是可变的,而受歧视的并集将不起作用。这主要是因为可变性导致判别字段
种类
的类型为
字符串
,而不是
正方形
矩形

关于深度只读和“const”有很多讨论:

当前版本的typescript是否有比上述版本更好的解决方法


.

我认为最简单的解决方法是类型断言:
let drawing:drawing=drawingingplicittype as drawing嘿@AlekseyL.,谢谢你的回复,我更新了游乐场,类型断言允许我编译,但也允许我犯各种错误。。。
nonExistentField
我也可以使用
new(class
解决方案犯错误,但我不能通过mistake@AlekseyL.我可以在每个
Shape
子对象上执行
as Shape
。。我将仔细研究一下,看看这是否比
新(类…