Programmatically created content type don't have a delete link
You could always take the dull axe approach and use a page_alter, eg, something along the lines of

function YOURMODULE_page_alter(&amp;$page) {

  if ($_GET['q']=='admin/structure/types') {

    $page['content']['system_main']['node_table']['#rows'][]=array(
      'Foo &lt;small&gt;(Machine name: foo)&lt;/small&gt;&lt;div class="description"&gt;Here is my description of foo&lt;/div&gt;',
      array('data' =&gt; l(t('edit'), 'admin/structure/types/manage/foo')),
      array('data' =&gt; l(t('manage fields'), 'admin/structure/types/manage/foo/fields')),
      array('data' =&gt; l(t('manage display'), 'admin/structure/types/manage/foo/display')),
      array('data' =&gt; l(t('delete'), 'admin/structure/types/manage/foo/delete')),
    );

  }

}


which will create a row for type foo.  

Per additions to the question:  since the row is showing up but just without the delete link, you can go in and create it similarly, eg,

$page['content']['system_main']['node_table']['#rows'][NUM][4]=array('data' =&gt; l('delete', 'admin/structure/types/manage/foo/delete'));


where NUM is the row number where your content type is found. You might also want to check out Adding an operation to Content Types and the page_alter() there on a possible way you might be able to easily figure out NUM.

Another addition:

Could you just do this in your module:

$info = array(
    'type' =&gt; $type,
    'name' =&gt; $name,
    'base' =&gt; 'node_content',
    'custom' =&gt; TRUE, // fake it out to think it was made via the UI...
);
$content_type = node_type_set_defaults($info);


A cursory glance through the code and node_type_set_defaults() suggests that the only thing this does is allow this delete link to be presented in this very form.