Another method to consider:
It has been noted in previous responses that it is impossible to completely avoid runtime actions; TypeScript transpires into JavaScript, primarily by discarding interface/type definitions, annotations, and assertions. The type system becomes erased, leaving your MyInterface
absent from the runtime code where it is needed.
Thus, a solution involves creating an array of keys that should be retained in the reduced object:
const myTestKeys = ["test"] as const;
This approach is delicate since any modifications to MyInterface
may go unnoticed by your code. To mitigate this issue, you can establish type alias definitions that trigger a compiler error if myTestKeys
does not align with keyof MyInterface
:
// An error will be thrown if myTestKeys contains entries not present in keyof MyInterface:
type ExtraTestKeysWarning<T extends never =
Exclude<typeof myTestKeys[number], keyof MyInterface>> = void;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Type 'UNION_OF_EXTRA_KEY_NAMES_HERE' does not satisfy the constraint 'never'
// An error will be thrown if myTestKeys lacks entries from keyof MyInterface:
type MissingTestKeysWarning<T extends never =
Exclude<keyof MyInterface, typeof myTestKeys[number]>> = void;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Type 'UNION_OF_MISSING_KEY_NAMES_HERE' does not satisfy the constraint 'never'
While this approach may lack elegance, modifying MyInterface
triggers an error in one or both of the above lines, prompting developers to adjust myTestKeys
.
Though methods exist to broaden the scope or reduce intrusiveness, TypeScript's primary function is to alert you via compiler warnings when changes occur unexpectedly within an interface; actual runtime behavior adjustments are rare.
With the desired keys defined, you can create a pick()
function to extract specific properties from an object:
function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K> {
return keys.reduce((o, k) => (o[k] = obj[k], o), {} as Pick<T, K>);
}
Applying this function to your test
object generates reduced
:
var test: MyTest = { test: "hello", newTest: "world" }
const reduced: MyInterface = pick(test, ...myTestKeys);
console.log(JSON.stringify(reduced)); // {"test": "hello;"}
Success!
Link to Play around with the code