I would try to implement PokeTypes by using an enum to define each PokeType. I'd have a dictionary that stored attacker, defender pairs as a key and the value would be the effectiveness of the attack. The "eff" function (which I'd call something like attack_effectiveness) would just be a get from the dictionary that defaulted to NORMAL_DAMAGE if the key wasn't contained in the dictionary. Later, I'd probably build up the dictionary from something that was easier to read and update to make maintaining it easier.
My point here is that I don't really see the point of using types to implement this functionality. Is my approach weak in some way that is solved by this?