Coder Social home page Coder Social logo

Comments (2)

jcalz avatar jcalz commented on April 27, 2024

Your bottom examples "work" because CommonUtilFns<Common> and CommonUtilFns<A | B> is not the same as CommonUtilFns<A> | CommonUtilFns<B>. You can't just distribute across unions. CommonUtilFns<T> is invariant in T:

declare let f: CommonUtilFns<A> | CommonUtilFns<B>
declare let g: CommonUtilFns<A | B>
f = g; // error!
g = f; // error!

Your top example doesn't work because it's essentially #30581. TS does not keep track of the identity of util here, just its type. If you have util1 and util2 both of type CommonUtilFns<A> | CommonUtilFns<B>, then if (util1.isAorB(val)) return util2.getProp(val) wouldn't be safe, right? That's the problem TS has. And that's been reported in #30581 and the recommended approach is detailed at #47109. That looks like the following:

interface UtilMap {
	A: A;
	B: B;
}

const utils: { [K in keyof UtilMap]: CommonUtilFns<UtilMap[K]> } = {
	A: {
		isAorB: (version: Common): version is A => !!(version as A).propA,
		getProp: (version: A) => ({ prop: version.propA }),
	},
	B: {
		isAorB: (version: Common): version is B => !!(version as B).propB,
		getProp: (version: B) => ({ prop: version.propB }),
	}
};

function apply<K extends keyof UtilMap>(util: (typeof utils)[K], val: Common) {
	return util.isAorB(val) ? util.getProp(val) : undefined
}

{
	const getProp = (val: Common) => {
		for (const util of Object.values(utils)) {
			const ret = apply(util, val);
			if (ret) return ret;
		}
		return null;
	};
}

Which, yes, is a lot of weird generic stuff. See #47109. Anyway I'd say this is essentially a duplicate of #30581.

Playground link

from typescript.

nmussy avatar nmussy commented on April 27, 2024

Thanks for the detailed explanation @jcalz! Your apply function was also more or less what I got recommended by Copilot, which is to do both the guarding and the prop extraction in a single function, with the same generic context. It's an understandable limitation, but a little frustrating because TS gets so close to getting it right.

I'm going to close this issue. Maintainers, feel free to mark it as a duplicate. And thanks again for your time Joe 👍

from typescript.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.