This is exactly how it is at my husband's high school: no penalties, no consequences, unlimited turning in of work until the end of the quarter. Didn't finish it all and ended up with a D or lower? Doesn't matter, because you can't be held back anyway.
Let's not even get into how kneecapped teachers are in classroom management. A student reported him for pointing at them and touching them when he was never fewer than 3 feet away pointing away from them. The students know they have the power now, and they're definitely not going to be told what to do.
There are other ways to introduce motivating factors that aren't tied to grade level retention. Sometimes this is done in secondary and tertiary education in the US, like preventing participation in extracurricular activities.
It was my grades in math that ultimately failed me out of my undergraduate CS program. My university had: Calculus 1, Calculus 2, Linear Algebra, Vector Geometry, Multi-Variable Calculus, Applied Combinatorics, Discrete Math, Differential Equations and maybe more that I don't remember. So many that CS majors could take one more math class and get a minor.
Yeah, I never thought this made sense, but so many people did; and, I always hear people on Slashdot talking about how programming IS math. None of that has been my personal experience, and I'm coming up on 21 years as software engineer. Discrete was the ONLY math course that I really enjoyed and did well in the first time around. For me, this always made sense.
I can count the times I've ever applied math past approximately high school algebra 1, on one hand. Period, in private life, in hobbies, at work. I'm not sure I've ever used any "college level" math, for anything at all.
I've, and other programmers I've known, gotten excited on the very few occasions anything even slightly mathematically-tricky came up, precisely because it almost never happens.
TypeScript doesn't require a class to use it, though, because it's structurally typed. All that "implements Foo" in this example does is make sure that you get a type error on the definition of "One" if it doesn't have the members of "Foo".
If "Two" didn't have a "name: string" member, then the error would be on the call to "test".
interface Foo {
name: string
}
class One implements Foo {
constructor(public name: string) {}
}
class Two {
constructor(public name: string) {}
}
function test(thing: Foo): void {
//...
}
test(new One('joe'));
test(new Two('jane'));