I have been trying to come up with a generic type to my method and restrict that type to an object with following requirements.
Below is the function I'm working with. However this function is used within a custom hook in React app.
function useCustomHook<T>(initialData: T[]) {
const [changes, setChanges] = React.useState<T[]>([])
// calling the method inside the hook with an element should be retrieved from changes
doSomething()
}
function doSomething<T>(obj: T) {
Object.entries(obj).forEach(([key, value]) => {
console.log(key, value)
})
}
// Type
type ExampleType = {
property1: number,
property2: string
}
// Interface
interface ExampleInterface {
property1: number;
property2: string;
}
It should throw an error for the following examples (basically it should not accept any primitive type such as string, number, boolean, null, undefined, ...):
doSomething('test')
doSomething(12)
doSomething(undefined)
And it should accept the following examples:
doSomething({})
doSomething({ property1: 12, property2: 'string'})
doSomething<ExampleType>({ property1: 12, property2: 'string'})
doSomething<ExampleInterface>({property1: 12, property2: 'string'})
I have already tried to change the method like so:
function doSomething<T extends Record<string, unknown>>
It works for most the examples (meaning it throws an error) but it does not work when an interface is used (throws Index signature is missing). Changing existing interfaces to types is not a solution and I think if the example function was a part of library I as the user of the library would like to have both the options - interface and type.
However it works if I change unknown to any but I believe using any should be avoided in Typescript.
I would appreciate any advice. I believe there's got to be a way to achieve it. Here is the sandbox: https://codesandbox.io/s/sweet-wildflower-hqr1t