Reputation: 105
I have the following Typescript code:
type Encoding = 'binary' | 'utf8';
type EncodingType = { binary: string, utf8: Uint8Array };
interface FS {
readFile: <T extends Encoding>(path: string, opts?: { encoding?: T, flags?: string }) => EncodingType[T];
}
type FSMethodNames = { [K in keyof FS]: (FS)[K] extends (...args: any[]) => any ? K : never }[keyof FS];
type FSMethodArgs = { [K in FSMethodNames]: Parameters<FS[K]> };
type FSMethodReturn = { [K in FSMethodNames]: ReturnType<FS[K]> };
FS<Method extends FSMethodNames>(method: Method, ...args: FSMethodArgs[Method]): FSMethodReturn[Method];
I am attempting to return a single type from the readFile
function depending on the provided value for encoding
, which is either string
or utf8
. As of now it is always returning string | Uint8Array
.
This is in a typescript index.d.ts
to add typings to preexisting JS code.
Example call:
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg';
const ffmpeg = createFFmpeg();
const video: File;
await ffmpeg.load();
// Get video from user...
// Write the file
ffmpeg.FS('writeFile', 'video', fetchFile(video));
// Misc. FFmpeg code to convert to gif...
// Read the result
// All three possible desired results shown
const dataA = ffmpeg.FS('readFile', 'out.gif'); // Should be string
const dataS = ffmpeg.FS('readFile', 'out.gif', { encoding: 'binary' }); // Should be string
const dataU = ffmpeg.FS('readFile', 'out.gif', { encoding: 'utf8'); // Should be Uint8Array
The current code works, but dataA
, dataS
, and dataU
are all of string | Uint8Array
type.
Upvotes: 0
Views: 95
Reputation: 25790
What you tried won't work because you need two generics, not one. FS
would have to be generic over the method
and over the encoding
, but there is only one generic defined.
If you can accept a curried API, then you can use this instead:
declare function FS<Method extends FSMethodNames>(method: Method): FS[Method];
const string = FS('readFile')('index.js', { encoding: 'binary' });
const uintarray = FS('readFile')('index.js', { encoding: 'utf8' });
const either = FS('readFile')('index.js');
Upvotes: 1