11import { getSource , readOnlyView , isInstanceOf } from './utils' ;
22
33const TYPED_FUN = Symbol ( 'typed function' ) ;
4+ const TYPED_PROP = Symbol ( 'typed property' ) ;
45const INNER_DATA = Symbol ( 'inner data' ) ;
56
67let activeArgList ;
78let activeArgIndex ;
89
10+ let insideConstructor = false ;
11+
912export const string = String ;
1013export const number = Number ;
1114export const boolean = Boolean ;
@@ -15,6 +18,13 @@ export function typ(typeDesc) {
1518 if ( ! type ) {
1619 throw new Error ( 'no type assigned' ) ;
1720 }
21+ if ( ( ! activeArgList || activeArgIndex === activeArgList . length ) && insideConstructor ) {
22+ return {
23+ [ TYPED_PROP ] : true ,
24+ type,
25+ def
26+ } ;
27+ }
1828 if ( activeArgList ) {
1929 let arg = activeArgList [ activeArgIndex ] ;
2030 activeArgIndex += 1 ;
@@ -60,13 +70,80 @@ export function fun(type, func) {
6070}
6171
6272export function cls ( classDesc ) {
63- if ( ! ( typeof classDesc === 'object' ) ) {
64- return classDesc ;
73+ let { constructor, ...proto } = classDesc ;
74+
75+ let realClass = false ;
76+ if ( typeof classDesc === 'function' ) {
77+ realClass = true ;
78+ constructor = classDesc ;
79+ proto = classDesc . prototype ;
6580 }
66- const { constructor, ...proto } = classDesc ;
6781
6882 const types = { } ;
69- const prototype = { } ;
83+
84+ let Con ;
85+ if ( realClass ) {
86+ Con = class Con extends classDesc {
87+
88+ constructor ( ...args ) {
89+ activeArgList = args ;
90+ activeArgIndex = 0 ;
91+ insideConstructor = true ;
92+
93+ try {
94+ super ( ) ;
95+ if ( activeArgList && activeArgIndex < activeArgList . length ) {
96+ throw new Error ( `wrong argument length? expected: ${ activeArgIndex } is: ${ activeArgList . length } ` ) ;
97+ }
98+ } finally {
99+ activeArgList = undefined ;
100+ activeArgIndex = - 999 ;
101+ insideConstructor = false ;
102+ }
103+
104+ Object . entries ( this )
105+ . forEach ( ( [ key , prop ] ) => {
106+ if ( ! prop || ! prop [ TYPED_PROP ] ) {
107+ return ;
108+ }
109+ const { type, def } = prop ;
110+
111+ if ( def !== undefined ) {
112+ checkType ( def , type , `check type for setter of type ${ type } ` ) ;
113+ }
114+ Object . defineProperty ( this , key , {
115+ get ( ) {
116+ return getInner ( this , key ) ;
117+ } ,
118+ set ( value ) {
119+ checkType ( value , type , `check type for setter of type ${ type } ` ) ;
120+ return setInner ( this , key , value ) ;
121+ }
122+ } ) ;
123+ } ) ;
124+ }
125+ } ;
126+ } else {
127+ Con = function Constructor ( ...args ) {
128+ if ( isInstanceOf ( this , Constructor ) ) {
129+ constructor . apply ( this , args ) ;
130+ } else {
131+ if ( ! args . length ) {
132+ return typ ( Con ) ;
133+ }
134+ const [ funDef ] = args ;
135+ if ( typeof funDef !== 'function' ) {
136+ if ( isInstanceOf ( funDef , Con ) ) {
137+ return funDef ;
138+ }
139+ throw new Error ( 'only fun definition allowd' ) ;
140+ }
141+ return fun ( Con , funDef ) ;
142+ }
143+ } ;
144+ }
145+
146+ const { prototype } = Con ;
70147
71148 Object . entries ( proto ) . forEach ( ( [ key , val ] ) => {
72149 if ( ! val ) {
@@ -95,25 +172,6 @@ export function cls(classDesc) {
95172 }
96173 } ) ;
97174 } ) ;
98- const Con = function Constructor ( ...args ) {
99- if ( isInstanceOf ( this , Constructor ) ) {
100- constructor . apply ( this , args ) ;
101- } else {
102- if ( ! args . length ) {
103- return typ ( Con ) ;
104- }
105- const [ funDef ] = args ;
106- if ( typeof funDef !== 'function' ) {
107- if ( isInstanceOf ( funDef , Con ) ) {
108- return funDef ;
109- }
110- throw new Error ( 'only fun definition allowd' ) ;
111- }
112- return fun ( Con , funDef ) ;
113- }
114- } ;
115-
116- Con . prototype = prototype ;
117175
118176 return readOnlyView ( Con ) ;
119177}
0 commit comments