Q:

How to replace properties using mapped types in Typescript

I have a Factory function that receives an object and if that object has  properties with a certain name, the factory converts those properties into methods.
How can I use mapped Types to correctly represent the type of the output object?
For example, let's say the convertible properties are foo, bar, baz:
interface IFactoryConfig {
   foo?: string;
   bar?: string;
   baz?: string;
}

And the replacement properties are:
interface IFactoryResult {
   foo(someParam: string): boolean;
   bar(): number;
   baz(otherParam: number): void;
}

If the input's type is
interface IInputObject {
   baz: string;
   notPredefined: string;
   aNumber: number;
   foo: string;
   aMethod(): void;
}

The factory replaces baz and foo with methods and returns:
interface IInputObject {
   baz(otherParam: number): void;
   notPredefined: string;
   aNumber: number;
   foo(someParam: string): boolean;
   aMethod(): void;
}

I'm trying to use mapped types to replace the properties:
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

interface IFactory {
   <InputType extends IFactoryConfig, ResultType>(config: InputType): Omit<InputType, keyof IFactoryConfig> & Pick<IFactoryResult, ?>;
}

I don't know what to put in the Pick<> to pick from IFactoryResult the properties that also appear on InputType.

A:

We're just talking about the type-level stuff here, not run-time behavior.  You can use conditional types inside your mapped type to perform the check. Here's a general property replacer:
type ReplaceProps<T, From, To> = { [K in keyof T]:
  K extends keyof From ? T[K] extends From[K] ? K extends keyof To ? To[K] 
  : T[K] : T[K] : T[K]
}

The idea is that any property in T whose key and value type is also found in From and whose key is found in To will be replaced by the property type in To; otherwise it leaves the property alone.
Then you can use it like this:
type IInputObjectOut = ReplaceProps<IInputObject, IFactoryConfig, IFactoryResult>;

and inspecting IInputObjectOut you can see it matches your desired type:
type IInputObjectOut = {
  baz: (otherParam: number) => void;
  notPredefined: string;
  aNumber: number;
  foo: (someParam: string) => boolean;
  aMethod: () => void;
}    

I think you could define your IFactory type like this, assuming it's supposed to be callable and behaves like ReplaceProps for its input type:
interface IFactory {
  <T>(config: T): ReplaceProps<T, IFactoryConfig, IFactoryResult>;
}

declare const iFact: IFactory;
declare const input: IInputObject;
input.foo; // string
input.aNumber; // number
const output = iFact(input); // ReplaceProps<IInputObject, IFactoryConfig, IFactoryResult>;
output.foo("hey"); // boolean
output.aNumber; // number

Does that work for you?  Hope it helps.  Good luck!

