Reputation: 166
I would liked to use object as a function parameter. This allow the caller to clearly define the arguments with the field names specified making reviews easier.
However, this is not very nice to deal with if you use implements
and extends
. This is what I am doing now.
src/domain/ServiceInterface.ts
export interface ServiceInterface {
doesThings(args: {
awesomeFieldName: string;
isThisAwesomeFieldName?: string;
ohWaitMoreAwesomeFieldName?: string;
}): boolean;
src/domain/ComposedServiceInterface.ts
import { ServiceInterface } from "./domain/ServiceInterface";
export type ComposedServiceInterface = ServiceInterface & { hello: () => string };
src/implementations/ComposedServiceImplementation.ts
import { ComposedServiceInterface } from "./domain/ComposedServiceInterface";
export class ComposedServiceImplementation implements ComposedServiceInterface {
doesThings(args: {
awesomeFieldName: string;
isThisAwesomeFieldName?: string;
ohWaitMoreAwesomeFieldName?: string;
}): boolean {
return true;
}
}
type
/ interface
for the object parametersrc/domain/ServiceInterface.ts
export type DoesThingsParameter = {
awesomeFieldName: string;
isThisAwesomeFieldName?: string;
ohWaitMoreAwesomeFieldName?: string;
};
export interface ServiceInterface {
doesThings(args: DoesThingsParameter): boolean;
src/domain/ComposedServiceInterface.ts
import { ServiceInterface } from "./domain/ServiceInterface";
export type ComposedServiceInterface = ServiceInterface & { hello: () => string };
src/implementations/ComposedServiceImplementation
import { ComposedServiceInterface } from "./domain/ComposedServiceInterface";
import { DoesThingsParameter } from "./domain/ServiceInterface";
export class ComposedServiceImplementation implements ComposedServiceInterface {
doesThings(args: DoesThingsParameter): boolean {
return true;
}
}
Gripe: I don't like this implemetation because src/implementations/ComposedServiceImplementation
should not need to import
from src/domain/ServiceInterface
since it only implements ComposedServiceInterface
Parameter
Utility Typeref: https://www.typescriptlang.org/docs/handbook/utility-types.html#parameterstype
I can't seem to get typescript to agree using a Class method e.g. Parameter<ComposedServiceInterface.doesThings>
Can someone offer any advice?
Upvotes: 3
Views: 603
Reputation: 736
The correct way of reusing types/interfaces is Attemp#1. Whenever you need to reuse some type definitions, you can extract it out. If you are concerned about importing from src/domain/ServiceInterface
in src/implementations/ComposedServiceImplementation
, you can always create a common file for types and add common types there and import in both of the files.
The one point to notice here is that you are only importing types from src/domain/ServiceInterface
so this import will be cleaned away after you compile your TS code. If you want to know whether you are importing a type of a value, you can use type only import like:
import type { DoesThingsParameter } from "./domain/ServiceInterface";
This will give your code more readability.
About Attemp#2, Try to avoid using complex utility types like Parameter
or ConstructorParameter
too frequently as their implementation is quite complex and Typescript has to do a lot of work. These types are generally used to get types for args for which you don't have access directly.
For example, if you are using a library that doesn't ship typescript definitions and you want to use a function from this library.
// some-library.ts
export function configure({
config1 = 'somevalue',
retries = 1
}) {
...code
}
Now you want to use this configure
function but want to create a configuration object outside.
// helper.ts
import { configure } from 'some-lib';
const configuration = {
config1: 'overrideValue',
unknownProperty: 'unknownValue'
}
function helper() {
const lib = configure(configuration)
...some work here
}
Now, the configuration has all the properties that the configure
function needs but it has added one new property that doesn't exist in configure
args. In this case, you have to use ParameterType to get the type definition of configure
args.
Upvotes: 1