{"action":"created","issue":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/4218","labels_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/4218/labels{/name}","comments_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/4218/comments","events_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/4218/events","html_url":"https://github.com/Microsoft/TypeScript/issues/4218","id":99690921,"number":4218,"title":"Forcing type guards for public API function arguments","user":{"login":"darrylring","id":2666,"avatar_url":"https://avatars.githubusercontent.com/u/2666?v=3","gravatar_id":"","url":"https://api.github.com/users/darrylring","html_url":"https://github.com/darrylring","followers_url":"https://api.github.com/users/darrylring/followers","following_url":"https://api.github.com/users/darrylring/following{/other_user}","gists_url":"https://api.github.com/users/darrylring/gists{/gist_id}","starred_url":"https://api.github.com/users/darrylring/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/darrylring/subscriptions","organizations_url":"https://api.github.com/users/darrylring/orgs","repos_url":"https://api.github.com/users/darrylring/repos","events_url":"https://api.github.com/users/darrylring/events{/privacy}","received_events_url":"https://api.github.com/users/darrylring/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-08-07T17:10:46Z","updated_at":"2015-08-07T21:50:26Z","closed_at":null,"body":"Is there room for some mechanism for forcing type guards on function argument? I don't know what the mechanism is, but I imagine it applying to files, functions, or classes. You could write every function argument as `something | void` but this would be a hassle to maintain and would confuse the definitions and documentation.\r\n\r\nHere's what I mean:\r\n\r\n```typescript\r\n// This has been marked as a public API function\r\nfunction doSomething(a: string): number {\r\n    // so `a` has type `void | string` here (or a new `unknown` type, not `any`)\r\n    return a.length; // and this would be an error.\r\n\r\n    if (typeof a === 'string') {\r\n        // Now we are certain `a` is type `string`\r\n        return a.length; // and this is okay!\r\n    }\r\n}\r\n```\r\n\r\nSo, `--declaration` would emit:\r\n\r\n```typescript\r\ndeclare function doSomething(a: string): number;\r\n```\r\n\r\nBut, for everything else this would be treated as:\r\n\r\n```typescript\r\nfunction doSomething(a: void | string): number;\r\n```\r\n\r\nTypeScript does not (and should not) do any run-time type checking. This is simply a mechanism for a library developer to ensure that public APIs are type safe. You're explicitly saying \"this should be a string, but I want to be sure.\""},"comment":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/comments/128840766","html_url":"https://github.com/Microsoft/TypeScript/issues/4218#issuecomment-128840766","issue_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/4218","id":128840766,"user":{"login":"mhegazy","id":8000722,"avatar_url":"https://avatars.githubusercontent.com/u/8000722?v=3","gravatar_id":"","url":"https://api.github.com/users/mhegazy","html_url":"https://github.com/mhegazy","followers_url":"https://api.github.com/users/mhegazy/followers","following_url":"https://api.github.com/users/mhegazy/following{/other_user}","gists_url":"https://api.github.com/users/mhegazy/gists{/gist_id}","starred_url":"https://api.github.com/users/mhegazy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mhegazy/subscriptions","organizations_url":"https://api.github.com/users/mhegazy/orgs","repos_url":"https://api.github.com/users/mhegazy/repos","events_url":"https://api.github.com/users/mhegazy/events{/privacy}","received_events_url":"https://api.github.com/users/mhegazy/received_events","type":"User","site_admin":false},"created_at":"2015-08-07T21:50:26Z","updated_at":"2015-08-07T21:50:26Z","body":"one option is to use decorators and metadata to inject runtime checks. here is a sample:\r\n\r\n```ts\r\n/// <reference path=\"c:/users/mhegazy/desktop/reflect-metadata.d.ts\" />\r\n// Polyfill for Reflect.metadata: https://github.com/rbuckton/ReflectDecorators\r\n\r\nfunction assert(condition: boolean, message: string) {\r\n    if (!condition) {\r\n        throw new Error(\"Assertion failed: \" + message);\r\n    }\r\n}\r\n\r\nfunction assertArgumentType(value: any, type: any) {\r\n    switch (type) {\r\n        case String: \r\n            return assert(typeof value === \"string\", \"parameter expected to be a string.\");\r\n        case Number:\r\n            return assert(typeof value === \"number\", \"parameter expected to be a number.\");\r\n        case Boolean:\r\n            return assert(typeof value === \"boolean\", \"parameter expected to be a boolean.\");\r\n        case undefined:\r\n            return;\r\n        default:\r\n            return assert(value instanceof type, \"parameter expected to be an instance of object.\");\r\n    }\r\n}\r\n\r\nfunction checkArguments(target: any, key: string| symbol, descriptor: PropertyDescriptor) {\r\n    let action = descriptor.value;\r\n    \r\n    // Get the types from the compiler emit. \r\n    let paramterTypes = Reflect.getMetadata(\"design:paramtypes\", target, key);\r\n\r\n    // replace the function with a new one\r\n    descriptor.value = function () {\r\n        // Validate the arguments\r\n        for (let i = 0; i < arguments.length; i++) {\r\n            assertArgumentType(arguments[i], paramterTypes[i]);\r\n        }\r\n\r\n        // Call the original function\r\n        return action.apply(this, arguments);\r\n    };\r\n    return descriptor;\r\n}\r\n\r\n\r\nclass C {\r\n    @checkArguments\r\n    public doSomething(a: string): number {\r\n        // so `a` is garanteed to be string at runtime, anythig else will throw\r\n        return a.length // and this would be an error.\r\n    }\r\n}\r\n\r\nvar c = new C();\r\n\r\nc.doSomething(\"s\"); // OK.\r\nc.doSomething(<any>1); // Runtime assert\r\n\r\n```\r\n\r\ncompile that with\r\n> tsc --expermentalDecorators --emitdecoratorMetadata --t es5"}}