My goal is to consolidate a group of nested string literals into one union.
The structure I am working with typically looks like this:
typechainTypes.factories.contracts
|
|----->Lock__factory (extends ContractFactory)
| |-----> contractName: string
|----->****** (this is a `export * as foo from bar`)
|-----> ****** (want to extract only if it extends ContractFactory; Extract<Foo, ContractFactory> type didn't work)
|-----> contractName: stringcontractName: string
This is what I envision in pseudocode:
type ContractFactories = typechainTypes.factories.contracts.**.* extends ContractFactory ? ___ : never;
type ContractNames = ContractFactories['contractName'];
In simpler terms:
type LookForFactory<T> = T.flatMap(foo => {
if (foo extends ContractFactory)
return foo;
else if (foo === undefined || foo === null || foo is SomePrimitive)
return never;
else
return LookForFactory<foo>;
}
type ContractNames = LookForFactory<typechainTypes.factories.contracts>;
The desired outcome should be a union consisting of these options:
typechainTypes.factories.contracts.Lock__factory.contractName
typechainTypes.factories.contracts.SomethingA.this_is_a__factory.contractName
typechainTypes.factories.contracts.SomethingB.SomethingC.this_is_a__factory.contractName
typechainTypes.factories.contracts.*.*.*.*.this_is_a__factory.contractName
If achieving an unknown depth is proving to be too complex, I would settle for a union of:
typechainTypes.factories.contracts.Lock__factory.contractName
typechainTypes.factories.contracts.UnknownNameA.UnknownNameB__factory.contractName
Initially, I attempted this using
Parameters<ethers.getContractFactory>[0]
, but the presence of any
in the final overload led to any[]
, which was not helpful. Finding a way to exclude the any[]
override remains a challenge.
Thank you!