diff --git a/types/parse/index.d.ts b/types/parse/index.d.ts index 45e678b437..94c142984b 100644 --- a/types/parse/index.d.ts +++ b/types/parse/index.d.ts @@ -1,6 +1,6 @@ -// Type definitions for parse 2.2.9 +// Type definitions for parse 2.9 // Project: https://parseplatform.org/ -// Definitions by: Ullisen Media Group +// Definitions by: Ullisen Media Group // David Poetzsch-Heffter // Cedric Kemp // Flavio Negrão @@ -10,6 +10,8 @@ // Alexandre Hétu Rivard // Diamond Lewis // Jong Eun Lee +// Colin Ulin +// Robert Helms // Julien Quere // Yago Tomé // Thibault MOCELLIN @@ -339,17 +341,17 @@ declare namespace Parse { * * Creates a new model with defined attributes. */ - class Object extends BaseObject { + class Object extends BaseObject { + id: string; createdAt: Date; updatedAt: Date; - attributes: any; + attributes: T; cid: string; changed: boolean; className: string; - constructor(className?: string, options?: any); - constructor(attributes?: string[], options?: any); + constructor(className?: string, attributes?: T, options?: any); static createWithoutData(id: string): T; static destroyAll(list: T[], options?: Object.DestroyAllOptions): Promise; @@ -388,7 +390,7 @@ declare namespace Parse { fetch(options?: Object.FetchOptions): Promise; fetchFromLocalDatastore(): Promise | void; fetchWithInclude(keys: string | Array>, options?: RequestOptions): Promise; - get(attr: string): any | undefined; + get>(attr: K): T[K]; getACL(): ACL | undefined; has(attr: string): boolean; hasChanged(attr: string): boolean; @@ -407,11 +409,24 @@ declare namespace Parse { removeAll(attr: string, items: any): this | false; revert(): void; revert(...keys: string[]): void; - save(attrs?: { [key: string]: any } | null, options?: Object.SaveOptions): Promise; - save(key: string, value: any, options?: Object.SaveOptions): Promise; - save(attrs: object, options?: Object.SaveOptions): Promise; - set(key: string, value: any, options?: Object.SetOptions): this | false; - set(attrs: object, options?: Object.SetOptions): this | false; + save( + attrs?: Partial | null, + options?: Object.SaveOptions + ): Promise; + save( + key: K, + value: T[K], + options?: Object.SaveOptions + ): Promise; + set( + attrs: Partial, + options?: Object.SetOptions + ): this | false; + set( + key: K, + value: T[K], + options?: Object.SetOptions + ): this | false; setACL(acl: ACL, options?: SuccessFailureOptions): this | false; toPointer(): Pointer; unPin(): Promise; @@ -452,7 +467,8 @@ declare namespace Parse { * Every Parse application installed on a device registered for * push notifications has an associated Installation object. */ - class Installation extends Object { + class Installation extends Object { + badge: any; channels: string[]; timeZone: any; @@ -713,7 +729,8 @@ subscription.on('close', () => {}); * A Parse.Role is a local representation of a role persisted to the Parse * cloud. */ - class Role extends Object { + class Role extends Object { + constructor(name: string, acl: ACL); getRoles(): Relation; @@ -722,7 +739,7 @@ subscription.on('close', () => {}); setName(name: string, options?: SuccessFailureOptions): any; } - class Config extends Object { + class Config extends Object { static get(options?: SuccessFailureOptions): Promise; static current(): Config; static save(attr: any): Promise; @@ -731,7 +748,7 @@ subscription.on('close', () => {}); escape(attr: string): any; } - class Session extends Object { + class Session extends Object { static current(): Promise; getSessionToken(): string; @@ -747,7 +764,8 @@ subscription.on('close', () => {}); * user specific methods, like authentication, signing up, and validation of * uniqueness.

*/ - class User extends Object { + class User extends Object { + static allowCustomUserClass(isAllowed: boolean): void; static become(sessionToken: string, options?: UseMasterKeyOption): Promise; static current(): User | undefined; diff --git a/types/parse/parse-tests.ts b/types/parse/parse-tests.ts index 36e59651f5..ee38af7e98 100644 --- a/types/parse/parse-tests.ts +++ b/types/parse/parse-tests.ts @@ -678,3 +678,123 @@ async function test_schema() { schema.update({ sessionToken: '' }).then(results => {}); } + +function test_generic_object() { + // Test Parse.Object instantiation with no type assertion + const objAny = new Parse.Object('TestObject') + objAny.attributes.whatever // any + objAny.attributes.createdAt // Date | undefined + objAny.attributes.updatedAt // Date | undefined + objAny.attributes.objectId // string | undefined + objAny.attributes.ACL // Parse.ACL | undefined + + // Test Parse.Object instantiation with manual type assertion + const objWithTypedAttrs = new Parse.Object<{ example: string }>('TestObject') + const exampleAttr = objWithTypedAttrs.attributes.example // string + const exampleGet = objWithTypedAttrs.get('example') // string + // const badAttr = objWithTypedAttrs.attributes.other // error + + // Test Parse.Object instantiation with attributes + const objWithAttrsAndOptions = new Parse.Object('TestObject', { example: 200 }) + const exampleAttrFromOptions = objWithAttrsAndOptions.attributes.example // number + const exampleGetFromOptions = objWithAttrsAndOptions.get('example') // number + // const badAttr2 = objWithAttrsAndOptions.attributes.other // error + +} + +function test_to_json_generic() { + + const exampleObjAny = new Parse.Object('TestObject') + const exampleJsonAny = exampleObjAny.toJSON() // Parse.Object.Attributes + + const exampleObjTyped = new Parse.Object('TestObject', { + exampleProp: false, + regexProp: new RegExp(''), + dateProp: new Date(), + parseProp: new Parse.Object('nestedObject', { + exampleProp: false, + regexProp: new RegExp(''), + dateProp: new Date(), + parseProp2: new Parse.Object('nestedObject', { + exampleProp2: false, + regexProp2: new RegExp(''), + dateProp2: new Date() + }) + }) + }) + const exampleJsonTyped = exampleObjTyped.toJSON() + exampleJsonTyped.exampleProp // boolean + exampleJsonTyped.dateProp // string + exampleJsonTyped.regexProp // string + exampleJsonTyped.parseProp.dateProp // string + exampleJsonTyped.parseProp.parseProp2.regexProp2 // string + exampleJsonTyped.parseProp.ACL // Parse.ACL | undefined + exampleJsonTyped.parseProp.objectId // string | undefined +} + +async function test_save_generic() { + const exampleObjAny = new Parse.Object('TestObject') + const savedAny = await exampleObjAny.save() + savedAny.attributes.anything // any + const savedNewExampleAttrAny = await exampleObjAny.save({ example: true }) + savedNewExampleAttrAny.attributes.anythingElse // any + + // Calling Parse.Object.save({}) with an existing attribute type checks + const exampleObjTyped = new Parse.Object<{ example: number; newExample: string }>('TestObject') + // const badSavedExampleAttr = await exampleObjTyped.save({ example: 'hello' }) // error + const savedExampleAttr = await exampleObjTyped.save({ example: 5 }) + savedExampleAttr.attributes.example // number + + // const badSavedExampleAttr = await exampleObjTyped.save({ createdAt: new Date() }) // never + + // Calling Parse.Object.save({}) with a new attribute adds that attribute as a known key + const savedNewExampleAttr = await exampleObjTyped.save({ newExample: 'hello' }) + savedNewExampleAttr.attributes.example // number + savedNewExampleAttr.attributes.newExample // string + + // Parse.Object.save(key, value) type checks existing keys + // const badSavedExampleAttr2 = await exampleObjTyped.save('example', 'hello') // error + const savedExampleAttr2 = await exampleObjTyped.save('example', 10) + savedExampleAttr2.attributes.example // number + + // const badSavedExampleAttr2 = await exampleObjTyped.save('createdAt', 10) // never + + // Parse.Object.save(key, value) with a new attribute adds that attribute as a known key + const savedNewExampleAttr2 = await exampleObjTyped.save('newExample', 'hello again') + savedNewExampleAttr2.attributes.example // number + savedNewExampleAttr2.attributes.newExample // string +} + +function test_set_generic() { + const exampleObjAny = new Parse.Object('TestObject') + exampleObjAny.attributes // any + exampleObjAny.set('propA', 'some value') + + const exampleObjTyped = new Parse.Object<{ example: boolean }>('TestObject') + + // Parse.Object.set({}) type checks existing keys, does not allow new keys + const setThingObj = exampleObjTyped.set({ example: false }) + setThingObj && setThingObj.attributes.example // boolean + // exampleObjTyped.set({ example: 100 }) // error + // const badSetNewThingObj = exampleObjTyped.set({ newExample: 'something' }) // error + + // Parse.Object.set(key, value) does not allow new keys + const setThingKeyVal = exampleObjTyped.set('example', false) + setThingKeyVal && setThingKeyVal.attributes.example // boolean + // const badSetThingNewKeyVal = exampleObjTyped.set('newExample', 100) // error +} + +async function test_query_generic() { + const exampleQuery = new Parse.Query>('TestObject') + + const gotExampleObj = await exampleQuery.get('objectId') + const gotAttrExample = gotExampleObj.attributes.example // string + const gotGetExample = gotExampleObj.get('example') // string + // const badGotGetExample = gotExampleObj.get('anything') // error + + const foundExampleObj = await exampleQuery.find() + foundExampleObj[0] && foundExampleObj[0].attributes.example // string + + const firstExampleObj = await exampleQuery.first() + firstExampleObj && firstExampleObj.attributes.example // string +} diff --git a/types/parse/tslint.json b/types/parse/tslint.json index 158db48e64..9c76d1ea7e 100644 --- a/types/parse/tslint.json +++ b/types/parse/tslint.json @@ -7,7 +7,6 @@ "ban-types": false, "callable-types": false, "comment-format": false, - "dt-header": false, "npm-naming": false, "eofline": false, "export-just-namespace": false,