sylvainpolletvillard / ObjectModel

Strong Dynamically Typed Object Modeling for JavaScript
http://objectmodel.js.org
MIT License
467 stars 30 forks source link

Add TypeScript definition file #61

Closed st-clair-clarke closed 6 years ago

st-clair-clarke commented 6 years ago

Hi, I like your objectmodel offering.

However, after reading it I am still uncertain if it is a good fit for typescript.

I see http://objectmodel.js.org/#doc-es6-classes

class Character extends Model({ lastName: String, firstName: String }){
   get fullName(){ return `${this.firstName} ${this.lastName}`; }

```}
but in TypeScript I would do the following:

class Character extends Model(lastName: String, firstName: String ){ lastName: String, firstName: String get fullName(){ return ${this.firstName} ${this.lastName}; } }



Is there any suggestion for typescript?
Are there any typscript definition type? (I don't see any in the module.

Cheers
sylvainpolletvillard commented 6 years ago

Hi,

I don't understand what you are trying to do by replacing the object model parameter with a list of parameters. Are you trying to define the constructor signature ? Because this is not the way you do it with TypeScript either. Here is the correct syntax for both TypeScript and ObjectModel API :

class Character extends Model({ lastName: String, firstName: String }){
    lastName: string;
    firstName: string;

    constructor(lastName: string, firstName: string){
        super({ lastName, firstName })
    }

    get fullName(){ return ${this.firstName} ${this.lastName}; }
}

Also note that TS and ObjectModel, respectively static and dynamic type checking, accomplish different goals. There is no interest in type-checking both statically and dynamically all your classes. For example, you may want to use TS for your application logic and ObjectModel to check data coming from the network or the user storage/inputs.

sylvainpolletvillard commented 6 years ago

I'll think about making a definition file for the library. Some of the things that the API does can not be expressed in a static way though.

st-clair-clarke commented 6 years ago

For example, you may want to use TS for your application logic and ObjectModel to check data coming from the network or the user storage/inputs.

How much duplication of code would be involved here? One class for typescript and the relevant ObjectModel class?

sylvainpolletvillard commented 6 years ago

No duplication at all, that's my point. You will have duplication only if you decide to type-check the same classes both statically and dynamically, which is useless most of the time in my opinion.

The introduction video is a good example of how ObjectModel can enhance existing Typescript code.

st-clair-clarke commented 6 years ago

Thanks. I will take a deeper dive into ObjectModel. You will see some more questions/queries from me on things that are not so clear.

Cheers

st-clair-clarke commented 6 years ago

Looking forward to the definition file. Trying to use as is I cannot get any help realtime with TypeScript and webstorm.

sylvainpolletvillard commented 6 years ago

@st-clair-clarke I added a definition file in latest version (3.2.1). Waiting for your feedback

st-clair-clarke commented 6 years ago

I am now getting webstorm IDE help. Thanks. After upgrading to 3.2.1, on all the following the code below

import { BasicModel } from 'objectmodel'

export const Primitive = BasicModel( [ Boolean, Number, String, Symbol ] )
    .as( 'Primitive' )

// Booleans-like
export const Falsy = BasicModel( [ Primitive, null, undefined ] )
    .assert( function isFalsy( x ) { return !x } )
    .as( 'Falsy' )
export const Truthy = BasicModel( [ Primitive, Object ] )
    .assert( function isTruthy( x ) { return !!x } )
    .as( 'Truthy' )

// Numbers
export const Integer = BasicModel( Number )
    .assert( Number.isInteger )
    .as( 'Integer' )
export const SafeInteger = BasicModel( Number )
    .assert( Number.isSafeInteger )
    .as( 'SafeInteger' )
export const FiniteNumber = BasicModel( Number )
    .assert( Number.isFinite )
    .as( 'FiniteNumber' )
export const PositiveNumber = BasicModel( Number )
    .assert( function isPositive( n ) { return n >= 0 } )
    .as( 'PositiveNumber' )
export const NegativeNumber = BasicModel( Number )
    .assert( function isNegative( n ) { return n <= 0 } )
    .as( 'NegativeNumber' )
export const PositiveInteger = PositiveNumber.extend()
                                             .assert( Number.isInteger )
                                             .as( 'PositiveInteger' )
export const NegativeInteger = NegativeNumber.extend()
                                             .assert( Number.isInteger )
                                             .as( 'NegativeInteger' )

// Strings
export const StringNotBlank = BasicModel( String )
    .assert( function isNotBlank( str ) { return str.trim().length > 0 } )
    .as( 'StringNotBlank' )
export const NormalizedString = BasicModel( String )
    .assert( function isNormalized( str ) { return str.normalize() === str } )
    .as( 'NormalizedString' )
export const TrimmedString = BasicModel( String )
    .assert( function isTrimmed( str ) { return str.trim() === str } )
    .as( 'TrimmedString' )

// Dates
export const PastDate = BasicModel( Date )
    .assert( function isInThePast( date ) { return date.getTime() < Date.now() } )
    .as( 'PastDate' )
export const FutureDate = BasicModel( Date )
    .assert( function isInTheFuture( date ) { return date.getTime() > Date.now() } )
    .as( 'FutureDate' )

// Arrays
export const ArrayNotEmpty = BasicModel( Array )
    .assert( function isNotEmpty( arr ) { return arr.length > 0 } )
    .as( 'ArrayNotEmpty' )
export const ArrayUnique = BasicModel( Array )
    .assert( function hasNoDuplicates( arr ) { return arr.every( ( x, i ) => arr.indexOf( x ) === i ) } )
    .as( 'ArrayUnique' )
export const ArrayDense = BasicModel( Array )
    .assert( function hasNoHoles( arr ) { return arr.filter( () => true ).length === arr.length } )
    .as( 'ArrayDense' )

...I am receiving the following errors

src/app/core/models.ts(4,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
src/app/core/models.ts(9,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
src/app/core/models.ts(12,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
src/app/core/models.ts(17,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
src/app/core/models.ts(20,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
src/app/core/models.ts(23,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
src/app/core/models.ts(26,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
src/app/core/models.ts(29,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
src/app/core/models.ts(40,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
src/app/core/models.ts(43,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
src/app/core/models.ts(46,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
src/app/core/models.ts(51,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
src/app/core/models.ts(54,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
src/app/core/models.ts(59,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
src/app/core/models.ts(62,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
src/app/core/models.ts(65,6): error TS2339: Property 'as' does not exist on type 'BasicModel'.
sylvainpolletvillard commented 6 years ago

This will be a good way to spot undocumented API. I add as to the website and the definition file

sylvainpolletvillard commented 6 years ago

added name, as and toString definition in 3.2.2

st-clair-clarke commented 6 years ago

Thanks for correcting the erors.

Cheers

sylvainpolletvillard commented 6 years ago

I am going to close this issue. If you spot other errors in the definition file, please open another issue. Thanks