Just like the other responses have pointed out, converting tuple labels into string literal types is not possible; the labels are purely for documentation purposes and do not impact the type system: the types [foo: string], [bar: string], and [string] are all interchangeable. Therefore, any approach to transform [foo: string] into {foo: string} must also apply to [bar: string] turning into {foo: string}. Consequently, capturing tuple labels must be abandoned.
The actual keys of a tuple consist of numeric strings such as "0" and "1". If you only wish to convert a tuple into a similar type with these numeric-like keys and exclude all array properties and methods, you can utilize the following solution:
type TupleToObject<T extends any[]> = Omit<T, keyof any[]>
This code snippet utilizes the Omit utility type to eliminate any tuple properties common in all arrays (e.g., length, push, etc). Alternatively, the following implementation achieves the same result:
type TupleToObject<T extends any[]> =
{ [K in keyof T as Exclude<K, keyof any[]>]: T[K] }
To demonstrate its functionality with your tuple type:
type StreamAgentObjectWithNumericlikeKeys = TupleToObject<StreamAgentParameters>
/* type StreamAgentObjectWithNumericlikeKeys = {
0: SessionAgent;
1: string;
2: boolean;
3: string;
4: ProducerOptions | null;
5: AbstractConnectionAgent;
6: string;
} */
You could also create a function that performs the same operation on actual values:
const tupleToObject = <T extends any[]>(
t: [...T]) => ({ ...t } as { [K in keyof T as Exclude< K, keyof any[]>]: T[K] });
const obj = tupleToObject(["a", 2, true]);
/* const obj: {
0: string;
1: number;
2: boolean;
} */
console.log(obj) // {0: "a", 1: 2, 2: true};
If you are willing to retain a tuple of property names alongside your tuple of types, you can write a function that maps the numeric tuple keys to their corresponding names:
type TupleToObjectWithPropNames<
T extends any[],
N extends Record<keyof TupleToObject<T>, PropertyKey>> =
{ [K in keyof TupleToObject<T> as N[K]]: T[K] };
type StreamAgentParameterNames = [
"session", "streamID", "isScreenShare", "connectionID",
"videoProducerOptions", "connection", "appData"
];
type StreamAgentObject =
TupleToObjectWithPropNames<StreamAgentParameters, StreamAgentParameterNames>
/*
type StreamAgentObject = {
session: SessionAgent
streamID: string
isScreenShare: boolean
connectionID: string
videoProducerOptions: ProducerOptions | null
connection: AbstractConnectionAgent
appData: string
}
*/
You can also create a function that applies the same transformation to real values:
const tupleToObjectWithPropNames = <T extends any[],
N extends PropertyKey[] & Record<keyof TupleToObject<T>, PropertyKey>>(
tuple: [...T], names: [...N]
) => Object.fromEntries(Array.from(tuple.entries()).map(([k, v]) => [(names as any)[k], v])) as
{ [K in keyof TupleToObject<T> as N[K]]: T[K] };
const objWithPropNames = tupleToObjectWithPropNames(["a", 2, true], ["str", "num", "boo"])
/* const objWithPropNames: {
str: string;
num: number;
boo: boolean;
} */
console.log(objWithPropNames); // {str: "a", num: 2, boo: true}
Link to Playground to test the code