Typescript Function/Object parameters












3















Why is typescript ES6 not detecting that objects are not functions?



find: (collection: string, query: object, sortQuery = {}, cb?: Function)  => {
socketManager.call('find', collection, query, sortQuery, cb);
}


Based off this function, you would assume that this would fail:



this._services._socket.methods.find('vendors', {type: 'repair'}, (errVen, resVen) => {}


Since there is no sortQuery object but instead a callback function. This is not giving me any type of error and means that typescript is allowing the callback as the object type.



How do I ensure this results in an error?










share|improve this question























  • Does it actually infer the sortQuery as an object type? or is it any?

    – Jonas Wilms
    Nov 27 '18 at 16:37











  • The same happens here, probably because functions are objects in JavaScript: typescriptlang.org/play/…

    – Frank Modica
    Nov 27 '18 at 16:38











  • Same results with this: find: (collection: string, query: object, sortQuery: object, cb?: Function) => { socketManager.call('find', collection, query, sortQuery, cb); }

    – user1779362
    Nov 27 '18 at 16:39













  • Any way to ensure 'Function' type and not an object?

    – user1779362
    Nov 27 '18 at 16:40






  • 2





    Do you know the parameters and return types of the sortQuery? You could define it more specifically

    – Frank Modica
    Nov 27 '18 at 16:44
















3















Why is typescript ES6 not detecting that objects are not functions?



find: (collection: string, query: object, sortQuery = {}, cb?: Function)  => {
socketManager.call('find', collection, query, sortQuery, cb);
}


Based off this function, you would assume that this would fail:



this._services._socket.methods.find('vendors', {type: 'repair'}, (errVen, resVen) => {}


Since there is no sortQuery object but instead a callback function. This is not giving me any type of error and means that typescript is allowing the callback as the object type.



How do I ensure this results in an error?










share|improve this question























  • Does it actually infer the sortQuery as an object type? or is it any?

    – Jonas Wilms
    Nov 27 '18 at 16:37











  • The same happens here, probably because functions are objects in JavaScript: typescriptlang.org/play/…

    – Frank Modica
    Nov 27 '18 at 16:38











  • Same results with this: find: (collection: string, query: object, sortQuery: object, cb?: Function) => { socketManager.call('find', collection, query, sortQuery, cb); }

    – user1779362
    Nov 27 '18 at 16:39













  • Any way to ensure 'Function' type and not an object?

    – user1779362
    Nov 27 '18 at 16:40






  • 2





    Do you know the parameters and return types of the sortQuery? You could define it more specifically

    – Frank Modica
    Nov 27 '18 at 16:44














3












3








3








Why is typescript ES6 not detecting that objects are not functions?



find: (collection: string, query: object, sortQuery = {}, cb?: Function)  => {
socketManager.call('find', collection, query, sortQuery, cb);
}


Based off this function, you would assume that this would fail:



this._services._socket.methods.find('vendors', {type: 'repair'}, (errVen, resVen) => {}


Since there is no sortQuery object but instead a callback function. This is not giving me any type of error and means that typescript is allowing the callback as the object type.



How do I ensure this results in an error?










share|improve this question














Why is typescript ES6 not detecting that objects are not functions?



find: (collection: string, query: object, sortQuery = {}, cb?: Function)  => {
socketManager.call('find', collection, query, sortQuery, cb);
}


Based off this function, you would assume that this would fail:



this._services._socket.methods.find('vendors', {type: 'repair'}, (errVen, resVen) => {}


Since there is no sortQuery object but instead a callback function. This is not giving me any type of error and means that typescript is allowing the callback as the object type.



How do I ensure this results in an error?







javascript typescript






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 27 '18 at 16:33









user1779362user1779362

387213




387213













  • Does it actually infer the sortQuery as an object type? or is it any?

    – Jonas Wilms
    Nov 27 '18 at 16:37











  • The same happens here, probably because functions are objects in JavaScript: typescriptlang.org/play/…

    – Frank Modica
    Nov 27 '18 at 16:38











  • Same results with this: find: (collection: string, query: object, sortQuery: object, cb?: Function) => { socketManager.call('find', collection, query, sortQuery, cb); }

    – user1779362
    Nov 27 '18 at 16:39













  • Any way to ensure 'Function' type and not an object?

    – user1779362
    Nov 27 '18 at 16:40






  • 2





    Do you know the parameters and return types of the sortQuery? You could define it more specifically

    – Frank Modica
    Nov 27 '18 at 16:44



















  • Does it actually infer the sortQuery as an object type? or is it any?

    – Jonas Wilms
    Nov 27 '18 at 16:37











  • The same happens here, probably because functions are objects in JavaScript: typescriptlang.org/play/…

    – Frank Modica
    Nov 27 '18 at 16:38











  • Same results with this: find: (collection: string, query: object, sortQuery: object, cb?: Function) => { socketManager.call('find', collection, query, sortQuery, cb); }

    – user1779362
    Nov 27 '18 at 16:39













  • Any way to ensure 'Function' type and not an object?

    – user1779362
    Nov 27 '18 at 16:40






  • 2





    Do you know the parameters and return types of the sortQuery? You could define it more specifically

    – Frank Modica
    Nov 27 '18 at 16:44

















Does it actually infer the sortQuery as an object type? or is it any?

– Jonas Wilms
Nov 27 '18 at 16:37





Does it actually infer the sortQuery as an object type? or is it any?

– Jonas Wilms
Nov 27 '18 at 16:37













The same happens here, probably because functions are objects in JavaScript: typescriptlang.org/play/…

– Frank Modica
Nov 27 '18 at 16:38





The same happens here, probably because functions are objects in JavaScript: typescriptlang.org/play/…

– Frank Modica
Nov 27 '18 at 16:38













Same results with this: find: (collection: string, query: object, sortQuery: object, cb?: Function) => { socketManager.call('find', collection, query, sortQuery, cb); }

– user1779362
Nov 27 '18 at 16:39







Same results with this: find: (collection: string, query: object, sortQuery: object, cb?: Function) => { socketManager.call('find', collection, query, sortQuery, cb); }

– user1779362
Nov 27 '18 at 16:39















Any way to ensure 'Function' type and not an object?

– user1779362
Nov 27 '18 at 16:40





Any way to ensure 'Function' type and not an object?

– user1779362
Nov 27 '18 at 16:40




2




2





Do you know the parameters and return types of the sortQuery? You could define it more specifically

– Frank Modica
Nov 27 '18 at 16:44





Do you know the parameters and return types of the sortQuery? You could define it more specifically

– Frank Modica
Nov 27 '18 at 16:44












2 Answers
2






active

oldest

votes


















1














With TypeScript Conditionals (TS v2.8), we can use Exclude to exclude Functions from the object type using Exclude<T, Function>:



let v = {
find: <T extends object>(collection: string, query: object, sortQuery: Exclude<T, Function>, cb?: (a: string, b: string) => void) => {
}
}

// Invalid
v.find('vendors', { type: 'repair' }, (a, b) => { })
v.find('vendors', { type: 'repair' }, 'I am a string', (a, b) => { })

// Valid
v.find('vendors', { type: 'repair' }, { dir: -1 })
v.find('vendors', { type: 'repair' }, { dir: -1 }, (a, b) => { })


A default parameter value can then be set like this:



sortQuery: Exclude<T, Function> = <any>{}


As you can see in the image below, errors are thrown for the first two calls to find, but not the second two calls to find:



TypeScript Exclude



The errors that then display are as follows:





  • [ts] Argument of type '(a, b) => void' is not assignable to parameter of type 'never'. [2345]

  • [ts] Argument of type '"I am a string"' is not assignable to parameter of type 'object'. [2345]







share|improve this answer


























  • This is a great solution. So one thing I didn't mention is that I have a script which is running through all my server functions and parsing through the files to grab the function names and the parameters to generate the functions on the client side. Would it be ok if I changed my script to do this on all functions?

    – user1779362
    Nov 27 '18 at 18:19











  • find: <T extends object>(collection: string, query: object, sortQuery: Exclude<T, Function> = <any>{}, cb?: Function) => { socketManager.call('find', collection, query, sortQuery, cb); }, findWithOptions: (collection: string, query: object, options: PaginationOptions, cb?: Function) => { socketManager.call('findWithOptions', collection, query, options, cb); }, insertDocument: (collection: string, document: object, cb?: Function) => { socketManager.call('insertDocument', collection, document, cb); },

    – user1779362
    Nov 27 '18 at 18:20











  • I don't know why you couldn't...

    – Get Off My Lawn
    Nov 27 '18 at 18:22



















0














Objects and functions are fundamentally the same thing, but typings help us disambiguate between their functionality.



Consider this:



const foo1: { (): string } = () => "";


The variable foo has a type of object, but that object is callable ... it's a function, and it can indeed be called, but you can't go setting a property called bar on it.



foo1(); // This works
foo1.bar = 5; // This, not so much.


Also consider this:



const foo2: { bar?: number; } = {};


The variable foo has a property called bar on it. That property can be set, but the object can't be called, as it's not typed as callable.



foo2.bar = 5; // This works
foo2(); // This, not so much.


So, lets have a look at your original typing:



sortQuery = {}


sortQuery is an object, but that's all that we know about it. It doesn't have any properties, it's not callable, it's just an object.



We've already seen that a function is an object, so you can assign a function to it just fine. But, you won't be able to call it, as it's not defined as callable.



const sortQuery: {} = () => ""; // This works.
sortQuery(); // This, not so much.
sortQuery.bar = 5; // Nor this.


If you have full control of the source code, then one way to solve this is to move from multiple parameters, to a single parameter with named properties:



const foo = (params: { collection: string, query: object, sortQuery: {}, cb?: Function }) => { };

foo({ collection: "", query: {}, sortQuery: {} }); // Fine
foo({ collection: "", query: {}, sortQuery: {}, cb: () => { } }); // Fine
foo({ collection: "", query: {}, cb: () => { } }); // Not Fine


This removes any ambiguity by requiring names, rather than relying on position in the function call.






share|improve this answer





















  • 1





    This is also a good solution to use objects. Unfortunately this would take a considerable amount of time to rework all the calls / create a script to fix all this. Good answer though.

    – user1779362
    Nov 27 '18 at 18:22











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53504160%2ftypescript-function-object-parameters%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














With TypeScript Conditionals (TS v2.8), we can use Exclude to exclude Functions from the object type using Exclude<T, Function>:



let v = {
find: <T extends object>(collection: string, query: object, sortQuery: Exclude<T, Function>, cb?: (a: string, b: string) => void) => {
}
}

// Invalid
v.find('vendors', { type: 'repair' }, (a, b) => { })
v.find('vendors', { type: 'repair' }, 'I am a string', (a, b) => { })

// Valid
v.find('vendors', { type: 'repair' }, { dir: -1 })
v.find('vendors', { type: 'repair' }, { dir: -1 }, (a, b) => { })


A default parameter value can then be set like this:



sortQuery: Exclude<T, Function> = <any>{}


As you can see in the image below, errors are thrown for the first two calls to find, but not the second two calls to find:



TypeScript Exclude



The errors that then display are as follows:





  • [ts] Argument of type '(a, b) => void' is not assignable to parameter of type 'never'. [2345]

  • [ts] Argument of type '"I am a string"' is not assignable to parameter of type 'object'. [2345]







share|improve this answer


























  • This is a great solution. So one thing I didn't mention is that I have a script which is running through all my server functions and parsing through the files to grab the function names and the parameters to generate the functions on the client side. Would it be ok if I changed my script to do this on all functions?

    – user1779362
    Nov 27 '18 at 18:19











  • find: <T extends object>(collection: string, query: object, sortQuery: Exclude<T, Function> = <any>{}, cb?: Function) => { socketManager.call('find', collection, query, sortQuery, cb); }, findWithOptions: (collection: string, query: object, options: PaginationOptions, cb?: Function) => { socketManager.call('findWithOptions', collection, query, options, cb); }, insertDocument: (collection: string, document: object, cb?: Function) => { socketManager.call('insertDocument', collection, document, cb); },

    – user1779362
    Nov 27 '18 at 18:20











  • I don't know why you couldn't...

    – Get Off My Lawn
    Nov 27 '18 at 18:22
















1














With TypeScript Conditionals (TS v2.8), we can use Exclude to exclude Functions from the object type using Exclude<T, Function>:



let v = {
find: <T extends object>(collection: string, query: object, sortQuery: Exclude<T, Function>, cb?: (a: string, b: string) => void) => {
}
}

// Invalid
v.find('vendors', { type: 'repair' }, (a, b) => { })
v.find('vendors', { type: 'repair' }, 'I am a string', (a, b) => { })

// Valid
v.find('vendors', { type: 'repair' }, { dir: -1 })
v.find('vendors', { type: 'repair' }, { dir: -1 }, (a, b) => { })


A default parameter value can then be set like this:



sortQuery: Exclude<T, Function> = <any>{}


As you can see in the image below, errors are thrown for the first two calls to find, but not the second two calls to find:



TypeScript Exclude



The errors that then display are as follows:





  • [ts] Argument of type '(a, b) => void' is not assignable to parameter of type 'never'. [2345]

  • [ts] Argument of type '"I am a string"' is not assignable to parameter of type 'object'. [2345]







share|improve this answer


























  • This is a great solution. So one thing I didn't mention is that I have a script which is running through all my server functions and parsing through the files to grab the function names and the parameters to generate the functions on the client side. Would it be ok if I changed my script to do this on all functions?

    – user1779362
    Nov 27 '18 at 18:19











  • find: <T extends object>(collection: string, query: object, sortQuery: Exclude<T, Function> = <any>{}, cb?: Function) => { socketManager.call('find', collection, query, sortQuery, cb); }, findWithOptions: (collection: string, query: object, options: PaginationOptions, cb?: Function) => { socketManager.call('findWithOptions', collection, query, options, cb); }, insertDocument: (collection: string, document: object, cb?: Function) => { socketManager.call('insertDocument', collection, document, cb); },

    – user1779362
    Nov 27 '18 at 18:20











  • I don't know why you couldn't...

    – Get Off My Lawn
    Nov 27 '18 at 18:22














1












1








1







With TypeScript Conditionals (TS v2.8), we can use Exclude to exclude Functions from the object type using Exclude<T, Function>:



let v = {
find: <T extends object>(collection: string, query: object, sortQuery: Exclude<T, Function>, cb?: (a: string, b: string) => void) => {
}
}

// Invalid
v.find('vendors', { type: 'repair' }, (a, b) => { })
v.find('vendors', { type: 'repair' }, 'I am a string', (a, b) => { })

// Valid
v.find('vendors', { type: 'repair' }, { dir: -1 })
v.find('vendors', { type: 'repair' }, { dir: -1 }, (a, b) => { })


A default parameter value can then be set like this:



sortQuery: Exclude<T, Function> = <any>{}


As you can see in the image below, errors are thrown for the first two calls to find, but not the second two calls to find:



TypeScript Exclude



The errors that then display are as follows:





  • [ts] Argument of type '(a, b) => void' is not assignable to parameter of type 'never'. [2345]

  • [ts] Argument of type '"I am a string"' is not assignable to parameter of type 'object'. [2345]







share|improve this answer















With TypeScript Conditionals (TS v2.8), we can use Exclude to exclude Functions from the object type using Exclude<T, Function>:



let v = {
find: <T extends object>(collection: string, query: object, sortQuery: Exclude<T, Function>, cb?: (a: string, b: string) => void) => {
}
}

// Invalid
v.find('vendors', { type: 'repair' }, (a, b) => { })
v.find('vendors', { type: 'repair' }, 'I am a string', (a, b) => { })

// Valid
v.find('vendors', { type: 'repair' }, { dir: -1 })
v.find('vendors', { type: 'repair' }, { dir: -1 }, (a, b) => { })


A default parameter value can then be set like this:



sortQuery: Exclude<T, Function> = <any>{}


As you can see in the image below, errors are thrown for the first two calls to find, but not the second two calls to find:



TypeScript Exclude



The errors that then display are as follows:





  • [ts] Argument of type '(a, b) => void' is not assignable to parameter of type 'never'. [2345]

  • [ts] Argument of type '"I am a string"' is not assignable to parameter of type 'object'. [2345]








share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 27 '18 at 18:21

























answered Nov 27 '18 at 17:34









Get Off My LawnGet Off My Lawn

13.6k1783176




13.6k1783176













  • This is a great solution. So one thing I didn't mention is that I have a script which is running through all my server functions and parsing through the files to grab the function names and the parameters to generate the functions on the client side. Would it be ok if I changed my script to do this on all functions?

    – user1779362
    Nov 27 '18 at 18:19











  • find: <T extends object>(collection: string, query: object, sortQuery: Exclude<T, Function> = <any>{}, cb?: Function) => { socketManager.call('find', collection, query, sortQuery, cb); }, findWithOptions: (collection: string, query: object, options: PaginationOptions, cb?: Function) => { socketManager.call('findWithOptions', collection, query, options, cb); }, insertDocument: (collection: string, document: object, cb?: Function) => { socketManager.call('insertDocument', collection, document, cb); },

    – user1779362
    Nov 27 '18 at 18:20











  • I don't know why you couldn't...

    – Get Off My Lawn
    Nov 27 '18 at 18:22



















  • This is a great solution. So one thing I didn't mention is that I have a script which is running through all my server functions and parsing through the files to grab the function names and the parameters to generate the functions on the client side. Would it be ok if I changed my script to do this on all functions?

    – user1779362
    Nov 27 '18 at 18:19











  • find: <T extends object>(collection: string, query: object, sortQuery: Exclude<T, Function> = <any>{}, cb?: Function) => { socketManager.call('find', collection, query, sortQuery, cb); }, findWithOptions: (collection: string, query: object, options: PaginationOptions, cb?: Function) => { socketManager.call('findWithOptions', collection, query, options, cb); }, insertDocument: (collection: string, document: object, cb?: Function) => { socketManager.call('insertDocument', collection, document, cb); },

    – user1779362
    Nov 27 '18 at 18:20











  • I don't know why you couldn't...

    – Get Off My Lawn
    Nov 27 '18 at 18:22

















This is a great solution. So one thing I didn't mention is that I have a script which is running through all my server functions and parsing through the files to grab the function names and the parameters to generate the functions on the client side. Would it be ok if I changed my script to do this on all functions?

– user1779362
Nov 27 '18 at 18:19





This is a great solution. So one thing I didn't mention is that I have a script which is running through all my server functions and parsing through the files to grab the function names and the parameters to generate the functions on the client side. Would it be ok if I changed my script to do this on all functions?

– user1779362
Nov 27 '18 at 18:19













find: <T extends object>(collection: string, query: object, sortQuery: Exclude<T, Function> = <any>{}, cb?: Function) => { socketManager.call('find', collection, query, sortQuery, cb); }, findWithOptions: (collection: string, query: object, options: PaginationOptions, cb?: Function) => { socketManager.call('findWithOptions', collection, query, options, cb); }, insertDocument: (collection: string, document: object, cb?: Function) => { socketManager.call('insertDocument', collection, document, cb); },

– user1779362
Nov 27 '18 at 18:20





find: <T extends object>(collection: string, query: object, sortQuery: Exclude<T, Function> = <any>{}, cb?: Function) => { socketManager.call('find', collection, query, sortQuery, cb); }, findWithOptions: (collection: string, query: object, options: PaginationOptions, cb?: Function) => { socketManager.call('findWithOptions', collection, query, options, cb); }, insertDocument: (collection: string, document: object, cb?: Function) => { socketManager.call('insertDocument', collection, document, cb); },

– user1779362
Nov 27 '18 at 18:20













I don't know why you couldn't...

– Get Off My Lawn
Nov 27 '18 at 18:22





I don't know why you couldn't...

– Get Off My Lawn
Nov 27 '18 at 18:22













0














Objects and functions are fundamentally the same thing, but typings help us disambiguate between their functionality.



Consider this:



const foo1: { (): string } = () => "";


The variable foo has a type of object, but that object is callable ... it's a function, and it can indeed be called, but you can't go setting a property called bar on it.



foo1(); // This works
foo1.bar = 5; // This, not so much.


Also consider this:



const foo2: { bar?: number; } = {};


The variable foo has a property called bar on it. That property can be set, but the object can't be called, as it's not typed as callable.



foo2.bar = 5; // This works
foo2(); // This, not so much.


So, lets have a look at your original typing:



sortQuery = {}


sortQuery is an object, but that's all that we know about it. It doesn't have any properties, it's not callable, it's just an object.



We've already seen that a function is an object, so you can assign a function to it just fine. But, you won't be able to call it, as it's not defined as callable.



const sortQuery: {} = () => ""; // This works.
sortQuery(); // This, not so much.
sortQuery.bar = 5; // Nor this.


If you have full control of the source code, then one way to solve this is to move from multiple parameters, to a single parameter with named properties:



const foo = (params: { collection: string, query: object, sortQuery: {}, cb?: Function }) => { };

foo({ collection: "", query: {}, sortQuery: {} }); // Fine
foo({ collection: "", query: {}, sortQuery: {}, cb: () => { } }); // Fine
foo({ collection: "", query: {}, cb: () => { } }); // Not Fine


This removes any ambiguity by requiring names, rather than relying on position in the function call.






share|improve this answer





















  • 1





    This is also a good solution to use objects. Unfortunately this would take a considerable amount of time to rework all the calls / create a script to fix all this. Good answer though.

    – user1779362
    Nov 27 '18 at 18:22
















0














Objects and functions are fundamentally the same thing, but typings help us disambiguate between their functionality.



Consider this:



const foo1: { (): string } = () => "";


The variable foo has a type of object, but that object is callable ... it's a function, and it can indeed be called, but you can't go setting a property called bar on it.



foo1(); // This works
foo1.bar = 5; // This, not so much.


Also consider this:



const foo2: { bar?: number; } = {};


The variable foo has a property called bar on it. That property can be set, but the object can't be called, as it's not typed as callable.



foo2.bar = 5; // This works
foo2(); // This, not so much.


So, lets have a look at your original typing:



sortQuery = {}


sortQuery is an object, but that's all that we know about it. It doesn't have any properties, it's not callable, it's just an object.



We've already seen that a function is an object, so you can assign a function to it just fine. But, you won't be able to call it, as it's not defined as callable.



const sortQuery: {} = () => ""; // This works.
sortQuery(); // This, not so much.
sortQuery.bar = 5; // Nor this.


If you have full control of the source code, then one way to solve this is to move from multiple parameters, to a single parameter with named properties:



const foo = (params: { collection: string, query: object, sortQuery: {}, cb?: Function }) => { };

foo({ collection: "", query: {}, sortQuery: {} }); // Fine
foo({ collection: "", query: {}, sortQuery: {}, cb: () => { } }); // Fine
foo({ collection: "", query: {}, cb: () => { } }); // Not Fine


This removes any ambiguity by requiring names, rather than relying on position in the function call.






share|improve this answer





















  • 1





    This is also a good solution to use objects. Unfortunately this would take a considerable amount of time to rework all the calls / create a script to fix all this. Good answer though.

    – user1779362
    Nov 27 '18 at 18:22














0












0








0







Objects and functions are fundamentally the same thing, but typings help us disambiguate between their functionality.



Consider this:



const foo1: { (): string } = () => "";


The variable foo has a type of object, but that object is callable ... it's a function, and it can indeed be called, but you can't go setting a property called bar on it.



foo1(); // This works
foo1.bar = 5; // This, not so much.


Also consider this:



const foo2: { bar?: number; } = {};


The variable foo has a property called bar on it. That property can be set, but the object can't be called, as it's not typed as callable.



foo2.bar = 5; // This works
foo2(); // This, not so much.


So, lets have a look at your original typing:



sortQuery = {}


sortQuery is an object, but that's all that we know about it. It doesn't have any properties, it's not callable, it's just an object.



We've already seen that a function is an object, so you can assign a function to it just fine. But, you won't be able to call it, as it's not defined as callable.



const sortQuery: {} = () => ""; // This works.
sortQuery(); // This, not so much.
sortQuery.bar = 5; // Nor this.


If you have full control of the source code, then one way to solve this is to move from multiple parameters, to a single parameter with named properties:



const foo = (params: { collection: string, query: object, sortQuery: {}, cb?: Function }) => { };

foo({ collection: "", query: {}, sortQuery: {} }); // Fine
foo({ collection: "", query: {}, sortQuery: {}, cb: () => { } }); // Fine
foo({ collection: "", query: {}, cb: () => { } }); // Not Fine


This removes any ambiguity by requiring names, rather than relying on position in the function call.






share|improve this answer















Objects and functions are fundamentally the same thing, but typings help us disambiguate between their functionality.



Consider this:



const foo1: { (): string } = () => "";


The variable foo has a type of object, but that object is callable ... it's a function, and it can indeed be called, but you can't go setting a property called bar on it.



foo1(); // This works
foo1.bar = 5; // This, not so much.


Also consider this:



const foo2: { bar?: number; } = {};


The variable foo has a property called bar on it. That property can be set, but the object can't be called, as it's not typed as callable.



foo2.bar = 5; // This works
foo2(); // This, not so much.


So, lets have a look at your original typing:



sortQuery = {}


sortQuery is an object, but that's all that we know about it. It doesn't have any properties, it's not callable, it's just an object.



We've already seen that a function is an object, so you can assign a function to it just fine. But, you won't be able to call it, as it's not defined as callable.



const sortQuery: {} = () => ""; // This works.
sortQuery(); // This, not so much.
sortQuery.bar = 5; // Nor this.


If you have full control of the source code, then one way to solve this is to move from multiple parameters, to a single parameter with named properties:



const foo = (params: { collection: string, query: object, sortQuery: {}, cb?: Function }) => { };

foo({ collection: "", query: {}, sortQuery: {} }); // Fine
foo({ collection: "", query: {}, sortQuery: {}, cb: () => { } }); // Fine
foo({ collection: "", query: {}, cb: () => { } }); // Not Fine


This removes any ambiguity by requiring names, rather than relying on position in the function call.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 27 '18 at 17:27

























answered Nov 27 '18 at 17:14









AndyJAndyJ

4,79923467




4,79923467








  • 1





    This is also a good solution to use objects. Unfortunately this would take a considerable amount of time to rework all the calls / create a script to fix all this. Good answer though.

    – user1779362
    Nov 27 '18 at 18:22














  • 1





    This is also a good solution to use objects. Unfortunately this would take a considerable amount of time to rework all the calls / create a script to fix all this. Good answer though.

    – user1779362
    Nov 27 '18 at 18:22








1




1





This is also a good solution to use objects. Unfortunately this would take a considerable amount of time to rework all the calls / create a script to fix all this. Good answer though.

– user1779362
Nov 27 '18 at 18:22





This is also a good solution to use objects. Unfortunately this would take a considerable amount of time to rework all the calls / create a script to fix all this. Good answer though.

– user1779362
Nov 27 '18 at 18:22


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53504160%2ftypescript-function-object-parameters%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Lallio

Futebolista

Jornalista