public static async Task <TsTypeDefinition> BuildTsTypeDefinitionAsync(Type type, TypeBuilderConfig config, GeneratorContext generatorContext) { var tsNamespace = GetTypescriptNamespace(type); if (type.IsEnum) { var members = Enum.GetNames(type); return(TsTypeDefinition.Enum(type.Name, members)); } else { var properties = TypeUtils.GetRelevantProperties(type); var fields = TypeUtils.GetRelevantFields(type); IList <Type> extends; if (type.IsInterface) { extends = type.GetInterfaces(); } else if (type.IsValueType || TypeUtils.Is <object>(type.BaseType)) { extends = new List <Type>(); } else { extends = new List <Type> { type.BaseType }; } foreach (var iface in type.GetInterfaces()) { // We look for default interface properties because we don't generate an extends clause for C# interfaces // but that means we loose default interface properties. If any of the types interface has default properties // we include it in the extends clause. var defaultInterfaceProperties = TypeUtils.GetRelevantProperties(iface).Where(p => p.GetGetMethod()?.IsAbstract == false); properties.AddRange(defaultInterfaceProperties); } var parentToAugument = GetParentTypeToAugument(type); var parentDefToAugument = default(TsTypeDefinition); if (parentToAugument != null) { parentDefToAugument = await BuildTsTypeDefinitionAsync(parentToAugument, config, generatorContext); } var members = new List <TsInterfaceMember>(); members.AddRange(properties.Select(m => BuildMember(m, type.GetInterfaces(), config, tsNamespace)).Where(x => x != null)); members.AddRange(fields.Select(m => BuildMember(m, type.GetInterfaces(), config, tsNamespace)).Where(x => x != null)); return(TsTypeDefinition.Interface(type, members, extends.Select(e => BuildTsTypeReference(e, config, tsNamespace, true)), type.GetTypeInfo().GenericTypeParameters.Select(TypeUtils.GetNameWithoutGenericArity), GetDerivedTypes(type, config, tsNamespace, generatorContext), parentDefToAugument, GetTypeMemberName(type))); } }