The interface ensures that all callers of functions that implement the interface supply the required arguments - data and toUpper.
Because TypeScript understands that JavaScript doesn't mind if you pass arguments that aren't used, it cleverly allows this in implementations.
Why is this okay? Because it means you can substitute any implementation of the interface without affecting calling code.
Example: You can substitute either IFormatter implementation and the code works.
interface IFormatter {
(data: string, toUpper: boolean): string;
};
var upperCaseFormatter: IFormatter = function (data: string) {
return data.toUpperCase();
}
var variableCaseFormatter: IFormatter = function (data: string, toUpper: boolean) {
if (toUpper) {
return data.toUpperCase();
}
return data.toLowerCase();
}
// Switch between these at will
//var formatter = upperCaseFormatter;
var formatter = variableCaseFormatter;
formatter("test", true);
If TypeScript didn't do this, your upperCaseFormatter would have to have to have a parameter called toUpper that wasn't used anywhere in the function - which makes the code less readable.
Videos
What are the types of TypeScript interfaces?
When should I use interfaces in TypeScript?
What is the main difference between types and interfaces in TypeScript?
The interface ensures that all callers of functions that implement the interface supply the required arguments - data and toUpper.
Because TypeScript understands that JavaScript doesn't mind if you pass arguments that aren't used, it cleverly allows this in implementations.
Why is this okay? Because it means you can substitute any implementation of the interface without affecting calling code.
Example: You can substitute either IFormatter implementation and the code works.
interface IFormatter {
(data: string, toUpper: boolean): string;
};
var upperCaseFormatter: IFormatter = function (data: string) {
return data.toUpperCase();
}
var variableCaseFormatter: IFormatter = function (data: string, toUpper: boolean) {
if (toUpper) {
return data.toUpperCase();
}
return data.toLowerCase();
}
// Switch between these at will
//var formatter = upperCaseFormatter;
var formatter = variableCaseFormatter;
formatter("test", true);
If TypeScript didn't do this, your upperCaseFormatter would have to have to have a parameter called toUpper that wasn't used anywhere in the function - which makes the code less readable.
The accepted answer is misleading, it may suggest to try and error additional arguments in production code with the sole purpose to cheat a type checking that does not exist in production.
To allow variants with different number of arguments for type checking you should state these variants as so-called overloads like
interface IFormatter {
(data: string, toUpper: boolean): string;
(data: string): string;
};
var upperCaseFormatter: IFormatter = function (data: string) {
return data.toUpperCase();
}
upperCaseFormatter("test"); // matches one-argument overload
upperCaseFormatter("test","false"); // matches two-arguments overload
The initial question why TypeScript does not do the same checks on defining functions as on executing functions keeps open. Lacking any official documentation you could speculate that there are some technical restrictions for TypeScript itself being written in TypeScript / JavaScript and wait if thins will change with TypeScript 7 being written in Go: https://github.com/microsoft/typescript-go?tab=readme-ov-file#typescript-7
In TypeScript, both interface and type can be used to describe complex types, including function types. However, they have some differences and use cases that may make one more suitable than the other in certain scenarios.
Interfaces in TypeScript define a contract that an object must adhere to. They are great for describing the shape of objects, and they can also describe function types. When you define a function using an interface, you're essentially defining a function signature that any function (that claims to implement this interface) must adhere to. This is useful, for instance, when you want to ensure that a function passed as a callback or a function stored in an object adheres to a specific.
In summary, whether to use an interface or a type alias to declare a function type in TypeScript depends on your specific needs. If you want to take advantage of features like class implementation and declaration merging, you might want to use an interface. But if you need more flexibility in representing various kinds of types, a type alias might be a better choice.
Using an interface, it ensures that the objects or functions you work with provide better type checking when it's annotated. In your case, the interface can be implemented this way:
interface SearchFunc {
(source: string,
subString: string): void;
}
The interface can be annotated this way:
const Search: SearchFunc = (source, subString) => {
// Your code goes here
};
For your reference:
Typescript Function Interface